Coverage Report

Created: 2026-01-09 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-sasl/sasl-oauth2.c
Line
Count
Source
1
/* Copyright (c) 2025 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
5
#include "sasl-oauth2.h"
6
7
static const unsigned char key_mask = BIT(0);
8
static const unsigned char value_mask = BIT(1);
9
10
static const unsigned char char_lookup[256] = {
11
  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  2,  0,  0, // 00
12
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 20
13
  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, // 20
14
  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, // 30
15
  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, // 40
16
  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2, // 50
17
  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, // 60
18
  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  0, // 70
19
20
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 80
21
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 90
22
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // a0
23
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // b0
24
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // c0
25
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // d0
26
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // e0
27
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // f0
28
};
29
30
31
int sasl_oauth2_kvpair_parse(const unsigned char *data, size_t size,
32
           const char **key_r, const char **value_r,
33
           const unsigned char **end_r,
34
           const char **error_r)
35
427
{
36
427
  const unsigned char *p = data, *pend = data + size, *poffset;
37
38
427
  i_assert(p < pend);
39
40
  /* RFC 7628, Section 3.1:
41
42
     kvsep          = %x01
43
     key            = 1*(ALPHA)
44
     value          = *(VCHAR / SP / HTAB / CR / LF )
45
     kvpair         = key "=" value kvsep
46
   */
47
48
  /* key            = 1*(ALPHA) */
49
427
  poffset = p;
50
2.37k
  while (p < pend && (char_lookup[*p] & key_mask) != 0x00)
51
1.94k
    p++;
52
53
  /* "=" */
54
427
  if (p == pend) {
55
3
    *error_r = "Missing value";
56
3
    return -1;
57
3
  }
58
424
  if (*p != '=') {
59
19
    *error_r = "Invalid character in key";
60
19
    return -1;
61
19
  }
62
405
  if (p == poffset) {
63
1
    *error_r = "Empty key name";
64
1
    return -1;
65
1
  }
66
404
  *key_r = t_strdup_until(poffset, p);
67
404
  p++;
68
69
  /* value          = *(VCHAR / SP / HTAB / CR / LF ) */
70
404
  poffset = p;
71
160k
  while (p < pend && (char_lookup[*p] & value_mask) != 0x00)
72
160k
    p++;
73
74
404
  if (p == pend) {
75
2
    *error_r = "Missing separator (0x01)";
76
2
    return -1;
77
2
  }
78
402
  if (*p != 0x01) {
79
5
    *error_r = "Invalid character in value";
80
5
    return -1;
81
5
  }
82
397
  *value_r = t_strdup_until(poffset, p);
83
397
  p++;
84
85
397
  *end_r = p;
86
397
  return 0;
87
402
}
88
89
bool sasl_oauth2_kvpair_check_value(const char *value)
90
946
{
91
946
  const unsigned char *p = (const unsigned char *)value;
92
946
  const unsigned char *pend = p + strlen(value);
93
94
166k
  while (p < pend && (char_lookup[*p] & value_mask) != 0x00)
95
165k
    p++;
96
97
946
  return (p == pend);
98
946
}