PostgreSQL Source Code git master
Loading...
Searching...
No Matches
saslprep.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  pg_saslprep_rc { SASLPREP_SUCCESS = 0 , SASLPREP_OOM = -1 , SASLPREP_INVALID_UTF8 = -2 , SASLPREP_PROHIBITED = -3 }
 

Functions

pg_saslprep_rc pg_saslprep (const char *input, char **output)
 

Enumeration Type Documentation

◆ pg_saslprep_rc

Enumerator
SASLPREP_SUCCESS 
SASLPREP_OOM 
SASLPREP_INVALID_UTF8 
SASLPREP_PROHIBITED 

Definition at line 20 of file saslprep.h.

21{
23 SASLPREP_OOM = -1, /* out of memory (only in frontend) */
24 SASLPREP_INVALID_UTF8 = -2, /* input is not a valid UTF-8 string */
25 SASLPREP_PROHIBITED = -3, /* output would contain prohibited characters */
pg_saslprep_rc
Definition saslprep.h:21
@ SASLPREP_INVALID_UTF8
Definition saslprep.h:24
@ SASLPREP_PROHIBITED
Definition saslprep.h:25
@ SASLPREP_OOM
Definition saslprep.h:23
@ SASLPREP_SUCCESS
Definition saslprep.h:22

Function Documentation

◆ pg_saslprep()

pg_saslprep_rc pg_saslprep ( const char input,
char **  output 
)
extern

Definition at line 1047 of file saslprep.c.

1048{
1049 char32_t *input_chars = NULL;
1050 char32_t *output_chars = NULL;
1051 int input_size;
1052 char *result;
1053 int result_size;
1054 int count;
1055 int i;
1056 bool contains_RandALCat;
1057 const unsigned char *p;
1058 unsigned char *outp;
1059 char32_t *wp;
1060
1061 /* Ensure we return *output as NULL on failure */
1062 *output = NULL;
1063
1064 /*
1065 * Convert the input from UTF-8 to an array of Unicode codepoints.
1066 *
1067 * This also checks that the input is a legal UTF-8 string.
1068 */
1070 if (input_size < 0)
1071 return SASLPREP_INVALID_UTF8;
1072 if (input_size >= MaxAllocSize / sizeof(char32_t))
1073 goto oom;
1074
1075 input_chars = ALLOC((input_size + 1) * sizeof(char32_t));
1076 if (!input_chars)
1077 goto oom;
1078
1079 p = (const unsigned char *) input;
1080 for (i = 0; i < input_size; i++)
1081 {
1083 p += pg_utf_mblen(p);
1084 }
1085 input_chars[i] = (char32_t) '\0';
1086
1087 /*
1088 * The steps below correspond to the steps listed in [RFC3454], Section
1089 * "2. Preparation Overview"
1090 */
1091
1092 /*
1093 * 1) Map -- For each character in the input, check if it has a mapping
1094 * and, if so, replace it with its mapping.
1095 */
1096 count = 0;
1097 for (i = 0; i < input_size; i++)
1098 {
1099 char32_t code = input_chars[i];
1100
1102 input_chars[count++] = 0x0020;
1104 {
1105 /* map to nothing */
1106 }
1107 else
1108 input_chars[count++] = code;
1109 }
1110 input_chars[count] = (char32_t) '\0';
1111 input_size = count;
1112
1113 if (input_size == 0)
1114 goto prohibited; /* don't allow empty password */
1115
1116 /*
1117 * 2) Normalize -- Normalize the result of step 1 using Unicode
1118 * normalization.
1119 */
1121 if (!output_chars)
1122 goto oom;
1123
1124 /*
1125 * 3) Prohibit -- Check for any characters that are not allowed in the
1126 * output. If any are found, return an error.
1127 */
1128 for (i = 0; i < input_size; i++)
1129 {
1130 char32_t code = input_chars[i];
1131
1133 goto prohibited;
1135 goto prohibited;
1136 }
1137
1138 /*
1139 * 4) Check bidi -- Possibly check for right-to-left characters, and if
1140 * any are found, make sure that the whole string satisfies the
1141 * requirements for bidirectional strings. If the string does not satisfy
1142 * the requirements for bidirectional strings, return an error.
1143 *
1144 * [RFC3454], Section "6. Bidirectional Characters" explains in more
1145 * detail what that means:
1146 *
1147 * "In any profile that specifies bidirectional character handling, all
1148 * three of the following requirements MUST be met:
1149 *
1150 * 1) The characters in section 5.8 MUST be prohibited.
1151 *
1152 * 2) If a string contains any RandALCat character, the string MUST NOT
1153 * contain any LCat character.
1154 *
1155 * 3) If a string contains any RandALCat character, a RandALCat character
1156 * MUST be the first character of the string, and a RandALCat character
1157 * MUST be the last character of the string."
1158 */
1159 contains_RandALCat = false;
1160 for (i = 0; i < input_size; i++)
1161 {
1162 char32_t code = input_chars[i];
1163
1165 {
1166 contains_RandALCat = true;
1167 break;
1168 }
1169 }
1170
1172 {
1173 char32_t first = input_chars[0];
1174 char32_t last = input_chars[input_size - 1];
1175
1176 for (i = 0; i < input_size; i++)
1177 {
1178 char32_t code = input_chars[i];
1179
1181 goto prohibited;
1182 }
1183
1186 goto prohibited;
1187 }
1188
1189 /*
1190 * Finally, convert the result back to UTF-8.
1191 */
1192 result_size = 0;
1193 for (wp = output_chars; *wp; wp++)
1194 {
1195 unsigned char buf[4];
1196
1198 result_size += pg_utf_mblen(buf);
1199 }
1200
1201 result = ALLOC(result_size + 1);
1202 if (!result)
1203 goto oom;
1204
1205 /*
1206 * There are no error exits below here, so the error exit paths don't need
1207 * to worry about possibly freeing "result".
1208 */
1209 outp = (unsigned char *) result;
1210 for (wp = output_chars; *wp; wp++)
1211 {
1214 }
1215 Assert((char *) outp == result + result_size);
1216 *outp = '\0';
1217
1220
1221 *output = result;
1222 return SASLPREP_SUCCESS;
1223
1225 if (input_chars)
1227 if (output_chars)
1229
1230 return SASLPREP_PROHIBITED;
1231
1232oom:
1233 if (input_chars)
1235 if (output_chars)
1237
1238 return SASLPREP_OOM;
1239}
#define Assert(condition)
Definition c.h:943
uint32_t char32_t
Definition c.h:1493
uint32 result
#define MaxAllocSize
Definition fe_memutils.h:22
FILE * input
FILE * output
int i
Definition isn.c:77
static char32_t utf8_to_unicode(const unsigned char *c)
Definition mbprint.c:53
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define pg_utf_mblen
Definition pg_wchar.h:633
static unsigned char * unicode_to_utf8(char32_t c, unsigned char *utf8string)
Definition pg_wchar.h:575
static int fb(int x)
static const char32_t LCat_codepoint_ranges[]
Definition saslprep.c:598
static const char32_t prohibited_output_ranges[]
Definition saslprep.c:117
static const char32_t commonly_mapped_to_nothing_ranges[]
Definition saslprep.c:82
#define IS_CODE_IN_TABLE(code, map)
Definition saslprep.c:966
static const char32_t unassigned_codepoint_ranges[]
Definition saslprep.c:158
#define ALLOC(size)
Definition saslprep.c:40
#define FREE(size)
Definition saslprep.c:41
static const char32_t RandALCat_codepoint_ranges[]
Definition saslprep.c:559
static int pg_utf8_string_len(const char *source)
Definition saslprep.c:1003
static const char32_t non_ascii_space_ranges[]
Definition saslprep.c:67
char32_t * unicode_normalize(UnicodeNormalizationForm form, const char32_t *input)
@ UNICODE_NFKC

References ALLOC, Assert, buf, commonly_mapped_to_nothing_ranges, fb(), FREE, i, input, IS_CODE_IN_TABLE, LCat_codepoint_ranges, MaxAllocSize, non_ascii_space_ranges, output, pg_utf8_string_len(), pg_utf_mblen, prohibited_output_ranges, RandALCat_codepoint_ranges, result, SASLPREP_INVALID_UTF8, SASLPREP_OOM, SASLPREP_PROHIBITED, SASLPREP_SUCCESS, unassigned_codepoint_ranges, UNICODE_NFKC, unicode_normalize(), unicode_to_utf8(), and utf8_to_unicode().

Referenced by pg_be_scram_build_secret(), pg_fe_scram_build_secret(), scram_init(), scram_verify_plain_password(), test_saslprep(), and test_saslprep_ranges().