10#include "ascii-chat/asciichat_errno.h"
11#include <ascii-chat/crypto/regex.h>
12#include <ascii-chat/common.h>
13#include <ascii-chat/util/pcre2.h>
32static const char *KNOWN_HOSTS_REGEX_PATTERN =
"^(?<ip_port>\\S+)"
37 "(?<hex_key>[0-9a-fA-F]{64})?"
38 "(?:\\s+(?<comment>.*))?)"
49static const char *SSH_PUBLIC_KEY_REGEX_PATTERN =
"ssh-ed25519"
51 "(?<base64_key>[A-Za-z0-9+/]+=*)"
52 "(?:\\s+(?<comment>.*))?";
63static const char *OPENSSH_PEM_REGEX_PATTERN =
64 "-----BEGIN OPENSSH PRIVATE KEY-----\\s*"
65 "(?<base64_data>[A-Za-z0-9+/=\\s]+?)"
66 "\\s*-----END OPENSSH PRIVATE KEY-----";
75static const char *GPG_KEYGRIP_REGEX_PATTERN =
"^grp:(?:[^:]*:){8}(?<keygrip>[A-Fa-f0-9]{40}):";
92static pcre2_code *crypto_regex_get_known_hosts(
void) {
93 if (g_known_hosts_regex == NULL) {
95 asciichat_pcre2_singleton_compile(KNOWN_HOSTS_REGEX_PATTERN, PCRE2_MULTILINE | PCRE2_UCP | PCRE2_UTF);
103static pcre2_code *crypto_regex_get_ssh_public_key(
void) {
104 if (g_ssh_public_key_regex == NULL) {
105 g_ssh_public_key_regex =
106 asciichat_pcre2_singleton_compile(SSH_PUBLIC_KEY_REGEX_PATTERN, PCRE2_CASELESS | PCRE2_UCP | PCRE2_UTF);
114static pcre2_code *crypto_regex_get_openssh_pem(
void) {
115 if (g_openssh_pem_regex == NULL) {
116 g_openssh_pem_regex = asciichat_pcre2_singleton_compile(OPENSSH_PEM_REGEX_PATTERN,
117 PCRE2_MULTILINE | PCRE2_DOTALL | PCRE2_UCP | PCRE2_UTF);
125static pcre2_code *crypto_regex_get_gpg_keygrip(
void) {
126 if (g_gpg_keygrip_regex == NULL) {
127 g_gpg_keygrip_regex = asciichat_pcre2_singleton_compile(GPG_KEYGRIP_REGEX_PATTERN, PCRE2_UCP | PCRE2_UTF);
137 char **comment_out) {
138 if (!line || !ip_port_out || !key_type_out || !hex_key_out || !comment_out) {
139 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
143 pcre2_code *regex = crypto_regex_get_known_hosts();
145 SET_ERRNO(ERROR_INVALID_STATE,
"Invalid validator state");
149 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
155 int rc = pcre2_jit_match(regex, (PCRE2_SPTR)line, strlen(line), 0,
160 pcre2_match_data_free(match_data);
170 pcre2_match_data_free(match_data);
173 if (!*ip_port_out || !*key_type_out) {
174 SAFE_FREE(*ip_port_out);
175 SAFE_FREE(*key_type_out);
176 SAFE_FREE(*hex_key_out);
177 SAFE_FREE(*comment_out);
185 if (!line || !base64_key_out || !comment_out) {
186 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
190 pcre2_code *regex = crypto_regex_get_ssh_public_key();
192 SET_ERRNO(ERROR_INVALID_STATE,
"Invalid validator state");
196 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
202 int rc = pcre2_jit_match(regex, (PCRE2_SPTR)line, strlen(line), 0,
207 pcre2_match_data_free(match_data);
215 pcre2_match_data_free(match_data);
218 if (!*base64_key_out) {
219 SAFE_FREE(*base64_key_out);
220 SAFE_FREE(*comment_out);
228 if (!file_content || !base64_data_out) {
229 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
233 pcre2_code *regex = crypto_regex_get_openssh_pem();
235 SET_ERRNO(ERROR_INVALID_STATE,
"Invalid validator state");
239 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
245 int rc = pcre2_jit_match(regex, (PCRE2_SPTR)file_content, strlen(file_content), 0,
250 pcre2_match_data_free(match_data);
257 pcre2_match_data_free(match_data);
260 if (!*base64_data_out) {
268 if (!line || !keygrip_out) {
269 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
273 pcre2_code *regex = crypto_regex_get_gpg_keygrip();
279 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
285 int rc = pcre2_jit_match(regex, (PCRE2_SPTR)line, strlen(line), 0,
290 pcre2_match_data_free(match_data);
297 pcre2_match_data_free(match_data);
pcre2_code * asciichat_pcre2_singleton_get_code(pcre2_singleton_t *singleton)
Get the compiled pcre2_code from a singleton handle.
char * asciichat_pcre2_extract_named_group(pcre2_code *regex, pcre2_match_data *match_data, const char *group_name, const char *subject)
Extract named substring from PCRE2 match data.
bool crypto_regex_match_public_key(const char *line, char **base64_key_out, char **comment_out)
bool crypto_regex_extract_gpg_keygrip(const char *line, char **keygrip_out)
bool crypto_regex_match_known_hosts(const char *line, char **ip_port_out, char **key_type_out, char **hex_key_out, char **comment_out)
bool crypto_regex_extract_pem_base64(const char *file_content, char **base64_data_out)
Represents a thread-safe compiled PCRE2 regex singleton.