Coverage Report

Created: 2025-07-11 06:28

/src/opensips/ut.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * - various general purpose functions
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History
23
 * ------
24
 * 2006-09-25  created by movind user2uid and group2gid from main.c (bogdan)
25
 */
26
27
28
#include <stdlib.h>
29
#include <pwd.h>
30
#include <grp.h>
31
#include "ut.h"
32
33
unsigned int int2str_buf_index = 0;
34
char int2str_buf[INT2STR_BUF_NO][INT2STR_MAX_LEN];
35
36
int tcp_timeout_con_get = 0;
37
int tcp_timeout_receive_fd = 0;
38
int tcp_timeout_send = 0;
39
40
/* make a null-termianted copy of the given string (in STR format) into
41
 * a static local buffer
42
 * !!IMPORTANT!! sequential calls do overwrite the previous values.
43
 */
44
char * NTcopy_str( str *s )
45
0
{
46
0
  static char *p=NULL;
47
0
  static unsigned int len = 0;
48
49
0
  if (p!=NULL) {
50
0
    if ( len < s->len+1 ) {
51
0
      p = pkg_realloc( p , s->len+1 );
52
0
      if (p==NULL) {
53
0
        LM_ERR("no more pkg mem (%d)\n", s->len+1);
54
0
        return NULL;
55
0
      }
56
0
      len = s->len+1;
57
0
    }
58
0
  } else {
59
0
    p = pkg_malloc(s->len+1);
60
0
    if (p==NULL) {
61
0
      LM_ERR("no more pkg mem (%d)\n", s->len+1);
62
0
      return NULL;
63
0
    }
64
0
    len = s->len+1;
65
0
  }
66
67
0
  memcpy( p , s->s, s->len);
68
0
  p[s->len] = 0;
69
70
0
  return p;
71
0
}
72
73
74
/* converts a username into uid:gid,
75
 * returns -1 on error & 0 on success */
76
int user2uid(int* uid, int* gid, char* user)
77
0
{
78
0
  char* tmp;
79
0
  struct passwd *pw_entry;
80
81
0
  if (user){
82
0
    *uid=strtol(user, &tmp, 10);
83
0
    if ((tmp==0) ||(*tmp)){
84
      /* maybe it's a string */
85
0
      pw_entry=getpwnam(user);
86
0
      if (pw_entry==0){
87
0
        goto error;
88
0
      }
89
0
      *uid=pw_entry->pw_uid;
90
0
      if (gid) *gid=pw_entry->pw_gid;
91
0
    }
92
0
    return 0;
93
0
  }
94
0
error:
95
0
  return -1;
96
0
}
97
98
99
int group2gid(int* gid, char* group)
100
0
{
101
0
  char* tmp;
102
0
  struct group  *gr_entry;
103
104
0
  if (group){
105
0
    *gid=strtol(group, &tmp, 10);
106
0
    if ((tmp==0) ||(*tmp)){
107
      /* maybe it's a string */
108
0
      gr_entry=getgrnam(group);
109
0
      if (gr_entry==0){
110
0
        goto error;
111
0
      }
112
0
      *gid=gr_entry->gr_gid;
113
0
    }
114
0
    return 0;
115
0
  }
116
0
error:
117
0
  return -1;
118
0
}
119
120
/* utility function to give each children a unique seed */
121
void seed_child(unsigned int seed)
122
0
{
123
0
  srand(seed);
124
0
}
125
126
127
int parse_reply_codes( str *options_reply_codes_str,
128
              int **options_reply_codes, int *options_codes_no)
129
0
{
130
0
  str code_str;
131
0
  unsigned int code;
132
0
  int index= 0;
133
0
  char* sep1, *sep2, *aux;
134
135
0
  *options_reply_codes = (int*)pkg_malloc(
136
0
      options_reply_codes_str->len/3 * sizeof(int));
137
138
0
  if(*options_reply_codes== NULL) {
139
0
    LM_ERR("no more memory\n");
140
0
    return -1;
141
0
  }
142
143
0
  sep1 = options_reply_codes_str->s;
144
0
  sep2 = strchr(options_reply_codes_str->s, ',');
145
146
0
  while(sep2 != NULL) {
147
148
0
    aux = sep2;
149
0
    while(*sep1 == ' ')
150
0
      sep1++;
151
152
0
    sep2--;
153
0
    while(*sep2 == ' ')
154
0
      sep2--;
155
156
0
    code_str.s = sep1;
157
0
    code_str.len = sep2-sep1+1;
158
159
0
    if(str2int(&code_str, &code)< 0) {
160
0
      LM_ERR("Bad format - not am integer [%.*s]\n",
161
0
          code_str.len, code_str.s);
162
0
      return -1;
163
0
    }
164
0
    if(code<100 ||code > 700) {
165
0
      LM_ERR("Wrong number [%d]- must be a valid SIP reply code\n",code);
166
0
      return -1;
167
0
    }
168
0
    (*options_reply_codes)[index] = code;
169
0
    index++;
170
171
0
    sep1 = aux +1;
172
0
    sep2 = strchr(sep1, ',');
173
0
  }
174
175
0
  while(*sep1 == ' ')
176
0
    sep1++;
177
0
  sep2 = options_reply_codes_str->s+options_reply_codes_str->len -1;
178
0
  while(*sep2 == ' ')
179
0
    sep2--;
180
181
0
  code_str.s = sep1;
182
0
  code_str.len = sep2 -sep1 +1;
183
0
  if(str2int(&code_str, &code)< 0) {
184
0
    LM_ERR("Bad format - not am integer [%.*s]\n",
185
0
        code_str.len, code_str.s);
186
0
    return -1;
187
0
  }
188
0
  if(code<100 ||code > 700) {
189
0
    LM_ERR("Wrong number [%d]- must be a valid SIP reply code\n", code);
190
0
    return -1;
191
0
  }
192
0
  (*options_reply_codes)[index] = code;
193
0
  index++;
194
195
0
  *options_codes_no = index;
196
197
0
  return 0;
198
0
}
199
200
static const char base64digits[] =
201
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
202
203
static const char base64urldigits[] =
204
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
205
206
static const char word64digits[] =
207
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+.";
208
209
static const char base32digits[] =
210
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
211
212
0
#define BAD     ((unsigned char)-1)
213
static const unsigned char base64val[] = {
214
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
215
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
216
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
217
52, 53, 54, 55,  56, 57, 58, 59,  60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
218
BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
219
15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,BAD, BAD,BAD,BAD,BAD,
220
BAD, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
221
41, 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,BAD, BAD,BAD,BAD,BAD,
222
223
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
224
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
225
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
226
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
227
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
228
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
229
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
230
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD
231
};
232
#define DECODE64(c)  (isascii(c) ? base64val[c] : BAD)
233
234
static const unsigned char base64urlval[] = {
235
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
236
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
237
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,62, BAD,BAD,
238
52, 53, 54, 55,  56, 57, 58, 59,  60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
239
BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
240
15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,BAD, BAD,BAD,BAD,63,
241
BAD, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
242
41, 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,BAD, BAD,BAD,BAD,BAD,
243
244
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
245
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
246
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
247
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
248
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
249
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
250
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
251
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD
252
};
253
254
static const unsigned char word64val[] = {
255
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
256
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
257
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD, 63,BAD,
258
52, 53, 54, 55,  56, 57, 58, 59,  60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
259
BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
260
15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,BAD, BAD,BAD,BAD,BAD,
261
BAD, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
262
41, 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,BAD, BAD,BAD,BAD,BAD,
263
264
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
265
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
266
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
267
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
268
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
269
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
270
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
271
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD
272
};
273
274
/* also accept lowercase letters as equivalent encoding characters
275
 * of uppercase letters */
276
static const unsigned char base32val[] = {
277
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
278
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
279
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
280
BAD,BAD, 26, 27,  28, 29, 30, 31, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
281
BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
282
15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25, BAD, BAD,BAD,BAD,BAD,
283
BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
284
15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25, BAD, BAD,BAD,BAD,BAD,
285
286
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
287
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
288
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
289
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
290
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
291
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
292
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
293
BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD
294
};
295
296
/* function that encodes to base64
297
 * output buffer is assumed to have the right length */
298
void base64encode(unsigned char *out, unsigned char *in, int inlen)
299
0
{
300
0
  for (; inlen >= 3; inlen -= 3)
301
0
  {
302
0
    *out++ = base64digits[in[0] >> 2];
303
0
    *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
304
0
    *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
305
0
    *out++ = base64digits[in[2] & 0x3f];
306
0
    in += 3;
307
0
  }
308
309
0
  if (inlen > 0)
310
0
  {
311
0
    unsigned char fragment;
312
313
0
    *out++ = base64digits[in[0] >> 2];
314
0
    fragment = (in[0] << 4) & 0x30;
315
316
0
    if (inlen > 1)
317
0
      fragment |= in[1] >> 4;
318
319
0
    *out++ = base64digits[fragment];
320
0
    *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
321
0
    *out++ = '=';
322
323
0
  }
324
0
}
325
326
/* function that encodes to base64URL
327
 * output buffer is assumed to have the right length */
328
void base64urlencode(unsigned char *out, unsigned char *in, int inlen)
329
0
{
330
0
  for (; inlen >= 3; inlen -= 3)
331
0
  {
332
0
    *out++ = base64urldigits[in[0] >> 2];
333
0
    *out++ = base64urldigits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
334
0
    *out++ = base64urldigits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
335
0
    *out++ = base64urldigits[in[2] & 0x3f];
336
0
    in += 3;
337
0
  }
338
339
0
  if (inlen > 0)
340
0
  {
341
0
    unsigned char fragment;
342
343
0
    *out++ = base64urldigits[in[0] >> 2];
344
0
    fragment = (in[0] << 4) & 0x30;
345
346
0
    if (inlen > 1)
347
0
      fragment |= in[1] >> 4;
348
349
0
    *out++ = base64urldigits[fragment];
350
0
    *out++ = (inlen < 2) ? '=' : base64urldigits[(in[1] << 2) & 0x3c];
351
0
    *out++ = '=';
352
353
0
  }
354
0
}
355
356
/* function that encodes to word64
357
 * output buffer is assumed to have the right length */
358
void word64encode(unsigned char *out, unsigned char *in, int inlen)
359
0
{
360
0
  for (; inlen >= 3; inlen -= 3)
361
0
  {
362
0
    *out++ = word64digits[in[0] >> 2];
363
0
    *out++ = word64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
364
0
    *out++ = word64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
365
0
    *out++ = word64digits[in[2] & 0x3f];
366
0
    in += 3;
367
0
  }
368
369
0
  if (inlen > 0)
370
0
  {
371
0
    unsigned char fragment;
372
373
0
    *out++ = word64digits[in[0] >> 2];
374
0
    fragment = (in[0] << 4) & 0x30;
375
376
0
    if (inlen > 1)
377
0
      fragment |= in[1] >> 4;
378
379
0
    *out++ = word64digits[fragment];
380
0
    *out++ = (inlen < 2) ? '-' : word64digits[(in[1] << 2) & 0x3c];
381
0
    *out++ = '-';
382
0
  }
383
0
}
384
385
/* function that encodes to base32
386
 * output buffer is assumed to have the right length */
387
void _base32encode(unsigned char *out, unsigned char *in, int inlen,
388
  unsigned char pad_char)
389
0
{
390
0
  for (; inlen >= 5; inlen -= 5)
391
0
  {
392
0
    *out++ = base32digits[in[0] >> 3];
393
0
    *out++ = base32digits[((in[0] << 2) & 0x1c) | (in[1] >> 6)];
394
0
    *out++ = base32digits[(in[1] >> 1) & 0x1f];
395
0
    *out++ = base32digits[((in[1] << 4) & 0x10) | (in[2] >> 4)];
396
0
    *out++ = base32digits[((in[2] << 1) & 0x1e) | (in[3] >> 7)];
397
0
    *out++ = base32digits[(in[3] >> 2) & 0x1f];
398
0
    *out++ = base32digits[((in[3] << 3) & 0x18) | (in[4] >> 5)];
399
0
    *out++ = base32digits[in[4] & 0x1f];
400
0
    in += 5;
401
0
  }
402
403
0
  if (inlen > 0)
404
0
  {
405
0
    unsigned char fragment;
406
407
0
    *out++ = base32digits[in[0] >> 3];
408
409
0
    fragment = (in[0] << 2) & 0x1c;
410
0
    if (inlen > 1)
411
0
      fragment |= in[1] >> 6;
412
0
    *out++ = base32digits[fragment];
413
414
0
    if (inlen < 2)
415
0
      goto pad;
416
417
0
    *out++ = base32digits[(in[1] >> 1) & 0x1f];
418
419
0
    fragment = (in[1] << 4) & 0x10;
420
0
    if (inlen > 2)
421
0
      fragment |= in[2] >> 4;
422
0
    *out++ = base32digits[fragment];
423
424
0
    if (inlen < 3)
425
0
      goto pad;
426
427
0
    fragment = (in[2] << 1) & 0x1e;
428
0
    if (inlen > 3)
429
0
      fragment |= in[3] >> 7;
430
0
    *out++ = base32digits[fragment];
431
432
0
    if (inlen < 4)
433
0
      goto pad;
434
435
0
    *out++ = base32digits[(in[3] >> 2) & 0x1f];
436
0
    *out++ = base32digits[(in[3] << 3) & 0x18];
437
0
pad:
438
0
    switch (inlen) {
439
0
    case 1:
440
0
      *out++ = pad_char;
441
0
      *out++ = pad_char;
442
      /* fall through */
443
0
    case 2:
444
0
      *out++ = pad_char;
445
      /* fall through */
446
0
    case 3:
447
0
      *out++ = pad_char;
448
0
      *out++ = pad_char;
449
      /* fall through */
450
0
    case 4:
451
0
      *out++ = pad_char;
452
0
    }
453
0
  }
454
0
}
455
456
/* function that decodes from base64
457
 * output buffer is assumed to have the right length */
458
int base64decode(unsigned char *out, unsigned char *in, int len)
459
0
{
460
0
  int i=0;
461
0
  unsigned char c1,c2,c3,c4;
462
0
  int out_len=0;
463
464
0
  while (len > i)
465
0
  {
466
0
    do
467
0
    {
468
0
      c1 = base64val[in[i++]];
469
0
    } while (i<len && c1 == BAD);
470
471
0
    if (c1 == BAD)
472
0
      break;
473
474
0
    do
475
0
    {
476
0
      c2 = base64val[in[i++]];
477
0
    } while (i<len && c2 == BAD);
478
479
0
    if (c2 == BAD)
480
0
      break;
481
482
0
    out[out_len++] = (c1 << 2) | ((c2 & 0x30) >> 4);
483
484
0
    do
485
0
    {
486
0
      c3 = in[i++];
487
0
      if (c3 == 61)
488
0
        return out_len;
489
490
0
      c3 = base64val[c3];
491
0
    } while (i<len && c3 == BAD);
492
493
0
    if (c3 == BAD)
494
0
      break;
495
496
0
    out[out_len++] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
497
498
0
    do
499
0
    {
500
0
      c4 = in[i++];
501
0
      if (c4 == 61)
502
0
        return out_len;
503
0
      c4 = base64val[c4];
504
0
    } while (i<len && c4 == BAD);
505
506
0
    if (c4 == BAD)
507
0
      break;
508
509
0
    out[out_len++] = ((c3 & 0x03) << 6) | c4;
510
0
  }
511
512
0
  return out_len;
513
0
}
514
515
/* function that decodes from base64URL
516
 * output buffer is assumed to have the right length */
517
int base64urldecode(unsigned char *out, unsigned char *in, int len)
518
0
{
519
0
  int i=0;
520
0
  unsigned char c1,c2,c3,c4;
521
0
  int out_len=0;
522
523
0
  while (len > i)
524
0
  {
525
0
    do
526
0
    {
527
0
      c1 = base64urlval[in[i++]];
528
0
    } while (i<len && c1 == BAD);
529
530
0
    if (c1 == BAD)
531
0
      break;
532
533
0
    do
534
0
    {
535
0
      c2 = base64urlval[in[i++]];
536
0
    } while (i<len && c2 == BAD);
537
538
0
    if (c2 == BAD)
539
0
      break;
540
541
0
    out[out_len++] = (c1 << 2) | ((c2 & 0x30) >> 4);
542
543
0
    do
544
0
    {
545
0
      c3 = in[i++];
546
0
      if (c3 == 61)
547
0
        return out_len;
548
549
0
      c3 = base64urlval[c3];
550
0
    } while (i<len && c3 == BAD);
551
552
0
    if (c3 == BAD)
553
0
      break;
554
555
0
    out[out_len++] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
556
557
0
    do
558
0
    {
559
0
      c4 = in[i++];
560
0
      if (c4 == 61)
561
0
        return out_len;
562
0
      c4 = base64urlval[c4];
563
0
    } while (i<len && c4 == BAD);
564
565
0
    if (c4 == BAD)
566
0
      break;
567
568
0
    out[out_len++] = ((c3 & 0x03) << 6) | c4;
569
0
  }
570
571
0
  return out_len;
572
0
}
573
574
/* function that decodes from word64
575
 * output buffer is assumed to have the right length */
576
int word64decode(unsigned char *out, unsigned char *in, int len)
577
0
{
578
0
  int i=0;
579
0
  unsigned char c1,c2,c3,c4;
580
0
  int out_len=0;
581
582
0
  while (len > i)
583
0
  {
584
0
    do
585
0
    {
586
0
      c1 = word64val[in[i++]];
587
0
    } while (i<len && c1 == BAD);
588
589
0
    if (c1 == BAD)
590
0
      break;
591
592
0
    do
593
0
    {
594
0
      c2 = word64val[in[i++]];
595
0
    } while (i<len && c2 == BAD);
596
597
0
    if (c2 == BAD)
598
0
      break;
599
600
0
    out[out_len++] = (c1 << 2) | ((c2 & 0x30) >> 4);
601
602
0
    do
603
0
    {
604
0
      c3 = in[i++];
605
0
      if (c3 == 61)
606
0
        return out_len;
607
608
0
      c3 = word64val[c3];
609
0
    } while (i<len && c3 == BAD);
610
611
0
    if (c3 == BAD)
612
0
      break;
613
614
0
    out[out_len++] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
615
616
0
    do
617
0
    {
618
0
      c4 = in[i++];
619
0
      if (c4 == 61)
620
0
        return out_len;
621
0
      c4 = word64val[c4];
622
0
    } while (i<len && c4 == BAD);
623
624
0
    if (c4 == BAD)
625
0
      break;
626
627
0
    out[out_len++] = ((c3 & 0x03) << 6) | c4;
628
0
  }
629
630
0
  return out_len;
631
0
}
632
633
/* function that decodes from base32
634
 * output buffer is assumed to have the right length */
635
int _base32decode(unsigned char *out, unsigned char *in, int len,
636
  unsigned char pad_char)
637
0
{
638
0
  int i=0;
639
0
  unsigned char c1,c2,c3,c4,c5,c6,c7,c8;
640
0
  int out_len=0;
641
642
0
  while (len > i)
643
0
  {
644
0
    do
645
0
    {
646
0
      c1 = base32val[in[i++]];
647
0
    } while (i<len && c1 == BAD);
648
649
0
    if (c1 == BAD)
650
0
      break;
651
652
0
    do
653
0
    {
654
0
      c2 = base32val[in[i++]];
655
0
    } while (i<len && c2 == BAD);
656
657
0
    if (c2 == BAD)
658
0
      break;
659
660
0
    out[out_len++] = (c1 << 3) | ((c2 & 0x1c) >> 2);
661
662
0
    do
663
0
    {
664
0
      c3 = in[i++];
665
0
      if (c3 == pad_char)
666
0
        return out_len;
667
0
      c3 = base32val[c3];
668
0
    } while (i<len && c3 == BAD);
669
670
0
    if (c3 == BAD)
671
0
      break;
672
673
0
    do
674
0
    {
675
0
      c4 = in[i++];
676
0
      if (c4 == pad_char)
677
0
        return out_len;
678
0
      c4 = base32val[c4];
679
0
    } while (i<len && c4 == BAD);
680
681
0
    if (c4 == BAD)
682
0
      break;
683
684
0
    out[out_len++] = ((c2 & 0x03) << 6) | (c3 << 1) | ((c4 & 0x10) >> 4);
685
686
0
    do
687
0
    {
688
0
      c5 = in[i++];
689
0
      if (c5 == pad_char)
690
0
        return out_len;
691
0
      c5 = base32val[c5];
692
0
    } while (i<len && c5 == BAD);
693
694
0
    if (c5 == BAD)
695
0
      break;
696
697
0
    out[out_len++] = ((c4 & 0x0f) << 4) | ((c5 & 0x1e) >> 1);
698
699
0
    do
700
0
    {
701
0
      c6 = in[i++];
702
0
      if (c6 == pad_char)
703
0
        return out_len;
704
0
      c6 = base32val[c6];
705
0
    } while (i<len && c6 == BAD);
706
707
0
    if (c6 == BAD)
708
0
      break;
709
710
0
    do
711
0
    {
712
0
      c7 = in[i++];
713
0
      if (c7 == pad_char)
714
0
        return out_len;
715
0
      c7 = base32val[c7];
716
0
    } while (i<len && c7 == BAD);
717
718
0
    if (c7 == BAD)
719
0
      break;
720
721
0
    out[out_len++] = ((c5 & 0x01) << 7) | (c6 << 2) | ((c7 & 0x18) >> 3);
722
723
0
    do
724
0
    {
725
0
      c8 = in[i++];
726
0
      if (c8 == pad_char)
727
0
        return out_len;
728
0
      c8 = base32val[c8];
729
0
    } while (i<len && c8 == BAD);
730
731
0
    if (c8 == BAD)
732
0
      break;
733
734
0
    out[out_len++] = ((c7 & 0x07) << 5) | c8;
735
0
  }
736
737
0
  return out_len;
738
0
}
739
740
char *db_url_escape(const str *url)
741
0
{
742
0
  static str buf;
743
0
  char *at, *slash, *scn;
744
0
  str upw;
745
746
0
  if (!url || !url->s)
747
0
    return NULL;
748
749
0
  if (pkg_str_extend(&buf, url->len + 6 + 1) < 0) {
750
0
    LM_ERR("oom\n");
751
0
    return NULL;
752
0
  }
753
754
  /* if there's no '@' sign, the URL has no password */
755
0
  at = q_memchr(url->s, '@', url->len);
756
0
  if (!at)
757
0
    goto url_is_safe;
758
759
  /* locate the end of the scheme (typical start for the user:password) */
760
0
  slash = q_memchr(url->s, '/', url->len);
761
0
  if (!slash || slash >= at)
762
0
    goto url_is_safe;
763
764
0
  upw.s = slash;
765
0
  upw.len = at - slash;
766
767
  /* if the semicolon is missing, the URL has no password (only username) */
768
0
  scn = q_memchr(upw.s, ':', upw.len);
769
0
  if (!scn)
770
0
    goto url_is_safe;
771
772
0
  sprintf(buf.s, "%.*s:xxxxxx@%.*s", (int)(scn - url->s), url->s,
773
0
      (int)(url->len - (at - url->s) - 1), at + 1);
774
775
0
  return buf.s;
776
777
0
url_is_safe:
778
0
  sprintf(buf.s, "%.*s", url->len, url->s);
779
0
  return buf.s;
780
0
}