ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
discovery_keys.h File Reference

Discovery Server Public Key Trust Management. More...

Go to the source code of this file.

Macros

#define ACDS_OFFICIAL_SERVER   ACDS_OFFICIAL_SERVER_HOSTNAME
 Official ACDS server hostname (automatic HTTPS key trust)
 
#define ACDS_OFFICIAL_KEY_SSH_URL   "https://discovery.ascii-chat.com/key.pub"
 Default HTTPS URLs for official ACDS keys.
 
#define ACDS_OFFICIAL_KEY_GPG_URL   "https://discovery.ascii-chat.com/key.gpg"
 
#define ACDS_KEYS_CACHE_DIR   "acds_keys"
 Key cache directory (relative to config dir)
 

Functions

asciichat_error_t discovery_keys_verify (const char *acds_server, const char *key_spec, uint8_t pubkey_out[32])
 Verify and load ACDS server public key.
 
asciichat_error_t discovery_keys_download_https (const char *url, uint8_t pubkey_out[32])
 Download key from HTTPS URL.
 
asciichat_error_t discovery_keys_load_file (const char *file_path, uint8_t pubkey_out[32])
 Load key from local file.
 
asciichat_error_t discovery_keys_get_cache_path (const char *acds_server, char *path_out, size_t path_size)
 Get cached key path for ACDS server.
 
asciichat_error_t discovery_keys_load_cached (const char *acds_server, uint8_t pubkey_out[32])
 Check if cached key exists and load it.
 
asciichat_error_t discovery_keys_save_cached (const char *acds_server, const uint8_t pubkey[32])
 Save key to cache.
 
asciichat_error_t discovery_keys_verify_change (const char *acds_server, const uint8_t old_pubkey[32], const uint8_t new_pubkey[32])
 Verify key change with user.
 
asciichat_error_t discovery_keys_clear_cache (const char *acds_server)
 Clear cached key for ACDS server.
 

Detailed Description

Discovery Server Public Key Trust Management.

This module handles verification and trust management for ACDS server public keys. It provides functionality to:

  • Download keys from HTTPS URLs using lib/crypto/http_client.h
  • Load keys from local files (SSH/GPG formats)
  • Special-case automatic trust for discovery-service.ascii-chat.com
  • Cache keys locally and detect changes (requires user verification)
  • Parse github:user and gitlab:user.gpg key specifications

Trust Model

Official ACDS Server (discovery-service.ascii-chat.com):

  • Automatically trusts keys downloaded from https://discovery-service.ascii-chat.com/key.pub or /key.gpg
  • First connection: downloads and caches key
  • Subsequent connections: uses cached key
  • Key changes: requires user verification (prevents MITM attacks)

Third-Party ACDS Servers:

  • Requires explicit –discovery-service-key configuration
  • Can be HTTPS URL, local file path, or github:user/gitlab:user specification
  • Keys are cached after first successful download/verification
  • Key changes require user verification

Usage

// Download and verify key from HTTPS URL
uint8_t pubkey[32];
asciichat_error_t result = discovery_keys_verify("acds.example.com",
"https://acds.example.com/key.pub",
pubkey);
// Automatic trust for official server
result = discovery_keys_verify("discovery-service.ascii-chat.com", NULL, pubkey);
// Load from local file
result = discovery_keys_verify("acds.example.com", "/path/to/key.pub", pubkey);
// GitHub key
result = discovery_keys_verify("acds.example.com", "github:zfogg", pubkey);
asciichat_error_t discovery_keys_verify(const char *acds_server, const char *key_spec, uint8_t pubkey_out[32])
Verify and load ACDS server public key.
unsigned char uint8_t
Definition common.h:56
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Definition in file discovery_keys.h.

Macro Definition Documentation

◆ ACDS_KEYS_CACHE_DIR

#define ACDS_KEYS_CACHE_DIR   "acds_keys"

Key cache directory (relative to config dir)

Definition at line 79 of file discovery_keys.h.

◆ ACDS_OFFICIAL_KEY_GPG_URL

#define ACDS_OFFICIAL_KEY_GPG_URL   "https://discovery.ascii-chat.com/key.gpg"

Definition at line 74 of file discovery_keys.h.

◆ ACDS_OFFICIAL_KEY_SSH_URL

#define ACDS_OFFICIAL_KEY_SSH_URL   "https://discovery.ascii-chat.com/key.pub"

Default HTTPS URLs for official ACDS keys.

Definition at line 73 of file discovery_keys.h.

◆ ACDS_OFFICIAL_SERVER

#define ACDS_OFFICIAL_SERVER   ACDS_OFFICIAL_SERVER_HOSTNAME

Official ACDS server hostname (automatic HTTPS key trust)

References the authoritative definition from network/acip/acds.h

Definition at line 68 of file discovery_keys.h.

Function Documentation

◆ discovery_keys_clear_cache()

asciichat_error_t discovery_keys_clear_cache ( const char *  acds_server)

Clear cached key for ACDS server.

Removes the cached key for the given ACDS server. Useful for testing or forcing key re-download.

Parameters
acds_serverACDS server hostname
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 208 of file discovery_keys.c.

208 {
209 if (!acds_server) {
210 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_clear_cache");
211 }
212
213 char cache_path[PLATFORM_MAX_PATH_LENGTH];
214 asciichat_error_t result = discovery_keys_get_cache_path(acds_server, cache_path, sizeof(cache_path));
215 if (result != ASCIICHAT_OK) {
216 return result;
217 }
218
219 if (platform_is_regular_file(cache_path)) {
220 if (remove(cache_path) != 0) {
221 return SET_ERRNO_SYS(ERROR_FILE_OPERATION, "Failed to delete cached key: %s", cache_path);
222 }
223 log_debug("Cleared cached ACDS key for server: %s", acds_server);
224 }
225
226 return ASCIICHAT_OK;
227}
asciichat_error_t discovery_keys_get_cache_path(const char *acds_server, char *path_out, size_t path_size)
Get cached key path for ACDS server.
#define SET_ERRNO_SYS(code, context_msg,...)
Set error code with custom message and system error context, returning the error code.
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_FILE_OPERATION
@ ERROR_INVALID_PARAM
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
int platform_is_regular_file(const char *path)
Check if a path is a regular file.
Definition util.c:124
#define PLATFORM_MAX_PATH_LENGTH
Definition system.c:69

References ASCIICHAT_OK, discovery_keys_get_cache_path(), ERROR_FILE_OPERATION, ERROR_INVALID_PARAM, log_debug, platform_is_regular_file(), PLATFORM_MAX_PATH_LENGTH, SET_ERRNO, and SET_ERRNO_SYS.

◆ discovery_keys_download_https()

asciichat_error_t discovery_keys_download_https ( const char *  url,
uint8_t  pubkey_out[32] 
)

Download key from HTTPS URL.

Downloads a public key from an HTTPS URL using lib/crypto/http_client.h. Supports both SSH (OpenSSH format) and GPG (ASCII-armored or binary) keys.

Parameters
urlHTTPS URL to download from
pubkey_outEd25519 public key output (32 bytes)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 80 of file discovery_keys.c.

80 {
81 if (!url || !pubkey_out) {
82 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_download_https");
83 }
84
85 log_debug("Downloading ACDS key from %s", url);
86
87 // Use existing parse_public_key infrastructure which handles HTTPS URLs
88 public_key_t key;
89 asciichat_error_t result = parse_public_key(url, &key);
90 if (result != ASCIICHAT_OK) {
91 return SET_ERRNO(ERROR_CRYPTO_KEY, "Failed to download and parse ACDS key from %s", url);
92 }
93
94 memcpy(pubkey_out, key.key, 32);
95 log_debug("Successfully downloaded and parsed ACDS key from %s", url);
96 return ASCIICHAT_OK;
97}
@ ERROR_CRYPTO_KEY
Definition error_codes.h:97
uint8_t key[32]
Definition key_types.h:71
asciichat_error_t parse_public_key(const char *input, public_key_t *key_out)
Parse SSH/GPG public key from any format (returns first key only)
Definition keys.c:28
Public key structure.
Definition key_types.h:69

References ASCIICHAT_OK, ERROR_CRYPTO_KEY, ERROR_INVALID_PARAM, public_key_t::key, log_debug, parse_public_key(), and SET_ERRNO.

◆ discovery_keys_get_cache_path()

asciichat_error_t discovery_keys_get_cache_path ( const char *  acds_server,
char *  path_out,
size_t  path_size 
)

Get cached key path for ACDS server.

Returns the local cache path for a given ACDS server's key. Path: ~/.config/ascii-chat/acds_keys/<hostname>/key.pub

Parameters
acds_serverACDS server hostname
path_outOutput buffer for cache path
path_sizeSize of output buffer
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 122 of file discovery_keys.c.

122 {
123 if (!acds_server || !path_out || path_size == 0) {
124 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_get_cache_path");
125 }
126
127 char *config_dir = get_config_dir();
128 if (!config_dir) {
129 return SET_ERRNO(ERROR_CONFIG, "Failed to get config directory");
130 }
131
132 // Path: ~/.config/ascii-chat/acds_keys/<hostname>/key.pub
133 safe_snprintf(path_out, path_size, "%s" ACDS_KEYS_CACHE_DIR PATH_SEPARATOR_STR "%s" PATH_SEPARATOR_STR "key.pub",
134 config_dir, acds_server);
135 SAFE_FREE(config_dir);
136
137 return ASCIICHAT_OK;
138}
#define ACDS_KEYS_CACHE_DIR
Key cache directory (relative to config dir)
#define SAFE_FREE(ptr)
Definition common.h:376
@ ERROR_CONFIG
Definition error_codes.h:57
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:148
#define PATH_SEPARATOR_STR
Definition filesystem.h:113
char * get_config_dir(void)
Get configuration directory path with XDG_CONFIG_HOME support.
Definition path.c:527

References ACDS_KEYS_CACHE_DIR, ASCIICHAT_OK, ERROR_CONFIG, ERROR_INVALID_PARAM, get_config_dir(), PATH_SEPARATOR_STR, SAFE_FREE, safe_snprintf(), and SET_ERRNO.

Referenced by discovery_keys_clear_cache(), discovery_keys_load_cached(), and discovery_keys_save_cached().

◆ discovery_keys_load_cached()

asciichat_error_t discovery_keys_load_cached ( const char *  acds_server,
uint8_t  pubkey_out[32] 
)

Check if cached key exists and load it.

Attempts to load a cached key for the given ACDS server.

Parameters
acds_serverACDS server hostname
pubkey_outEd25519 public key output (32 bytes)
Returns
ASCIICHAT_OK if cached key exists and loaded successfully, error otherwise

Definition at line 140 of file discovery_keys.c.

140 {
141 if (!acds_server || !pubkey_out) {
142 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_load_cached");
143 }
144
145 char cache_path[PLATFORM_MAX_PATH_LENGTH];
146 asciichat_error_t result = discovery_keys_get_cache_path(acds_server, cache_path, sizeof(cache_path));
147 if (result != ASCIICHAT_OK) {
148 return result;
149 }
150
151 // Check if cached key exists
152 if (!platform_is_regular_file(cache_path)) {
153 return SET_ERRNO(ERROR_FILE_NOT_FOUND, "No cached key for ACDS server: %s", acds_server);
154 }
155
156 // Load cached key using existing infrastructure
157 return discovery_keys_load_file(cache_path, pubkey_out);
158}
asciichat_error_t discovery_keys_load_file(const char *file_path, uint8_t pubkey_out[32])
Load key from local file.
@ ERROR_FILE_NOT_FOUND

References ASCIICHAT_OK, discovery_keys_get_cache_path(), discovery_keys_load_file(), ERROR_FILE_NOT_FOUND, ERROR_INVALID_PARAM, platform_is_regular_file(), PLATFORM_MAX_PATH_LENGTH, and SET_ERRNO.

Referenced by discovery_keys_verify().

◆ discovery_keys_load_file()

asciichat_error_t discovery_keys_load_file ( const char *  file_path,
uint8_t  pubkey_out[32] 
)

Load key from local file.

Loads a public key from a local file. Supports:

  • OpenSSH format (.pub files)
  • GPG ASCII-armored format (.asc, .gpg)
  • GPG binary format
Parameters
file_pathPath to key file
pubkey_outEd25519 public key output (32 bytes)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 99 of file discovery_keys.c.

99 {
100 if (!file_path || !pubkey_out) {
101 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_load_file");
102 }
103
104 log_debug("Loading ACDS key from file: %s", file_path);
105
106 // Use existing parse_public_key infrastructure which handles file paths
107 public_key_t key;
109 if (result != ASCIICHAT_OK) {
110 return SET_ERRNO(ERROR_CRYPTO_KEY, "Failed to load ACDS key from file: %s", file_path);
111 }
112
113 memcpy(pubkey_out, key.key, 32);
114 log_debug("Successfully loaded ACDS key from file: %s", file_path);
115 return ASCIICHAT_OK;
116}
char file_path[PLATFORM_MAX_PATH_LENGTH]
Definition mmap.c:39

References ASCIICHAT_OK, ERROR_CRYPTO_KEY, ERROR_INVALID_PARAM, file_path, public_key_t::key, log_debug, parse_public_key(), and SET_ERRNO.

Referenced by discovery_keys_load_cached().

◆ discovery_keys_save_cached()

asciichat_error_t discovery_keys_save_cached ( const char *  acds_server,
const uint8_t  pubkey[32] 
)

Save key to cache.

Caches a public key for the given ACDS server.

Parameters
acds_serverACDS server hostname
pubkeyPublic key to cache (32 bytes)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 160 of file discovery_keys.c.

160 {
161 if (!acds_server || !pubkey) {
162 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_save_cached");
163 }
164
165 char cache_path[PLATFORM_MAX_PATH_LENGTH];
166 asciichat_error_t result = discovery_keys_get_cache_path(acds_server, cache_path, sizeof(cache_path));
167 if (result != ASCIICHAT_OK) {
168 return result;
169 }
170
171 // Create cache directory if it doesn't exist
172 char dir_path[PLATFORM_MAX_PATH_LENGTH];
173 safe_snprintf(dir_path, sizeof(dir_path), "%s", cache_path);
174
175 // Find the last path separator (handle both / and \ for cross-platform compatibility)
176 char *last_sep = strrchr(dir_path, '\\');
177 if (!last_sep) {
178 last_sep = strrchr(dir_path, '/');
179 }
180
181 if (last_sep) {
182 *last_sep = '\0';
183 if (!platform_is_directory(dir_path)) {
184 asciichat_error_t result = platform_mkdir(dir_path, 0700);
185 if (result != ASCIICHAT_OK) {
186 return SET_ERRNO(ERROR_FILE_OPERATION, "Failed to create ACDS key cache directory: %s", dir_path);
187 }
188 }
189 }
190
191 // Save key in OpenSSH public key format
192 FILE *f = platform_fopen("file_stream", cache_path, "w");
193 if (!f) {
194 return SET_ERRNO_SYS(ERROR_FILE_OPERATION, "Failed to create cache file: %s", cache_path);
195 }
196
197 // Convert binary Ed25519 key to base64 for OpenSSH format
198 char base64_key[128];
199 sodium_bin2base64(base64_key, sizeof(base64_key), pubkey, 32, sodium_base64_VARIANT_ORIGINAL);
200
201 fprintf(f, "ssh-ed25519 %s acds-cached-key\n", base64_key);
202 fclose(f);
203
204 log_debug("Cached ACDS key for server: %s", acds_server);
205 return ASCIICHAT_OK;
206}
asciichat_error_t platform_mkdir(const char *path, int mode)
Create a directory.
int platform_is_directory(const char *path)
Check if a path is a directory.
FILE * platform_fopen(const char *name, const char *filename, const char *mode)
Safe file open stream (fopen replacement)

References ASCIICHAT_OK, discovery_keys_get_cache_path(), ERROR_FILE_OPERATION, ERROR_INVALID_PARAM, log_debug, platform_fopen(), platform_is_directory(), PLATFORM_MAX_PATH_LENGTH, platform_mkdir(), safe_snprintf(), SET_ERRNO, and SET_ERRNO_SYS.

Referenced by discovery_keys_verify().

◆ discovery_keys_verify()

asciichat_error_t discovery_keys_verify ( const char *  acds_server,
const char *  key_spec,
uint8_t  pubkey_out[32] 
)

Verify and load ACDS server public key.

This function handles all ACDS key verification scenarios:

Automatic Trust (discovery-service.ascii-chat.com only):

  • If acds_server == "discovery-service.ascii-chat.com" and key_spec == NULL:
    • Downloads from ACDS_OFFICIAL_KEY_SSH_URL or ACDS_OFFICIAL_KEY_GPG_URL
    • Caches key locally
    • Trusts without user verification (first time)
    • Requires user verification if key changes

Explicit Key Specification:

  • HTTPS URL: Downloads key from URL, caches it
  • Local file: Loads key from file path
  • github:user: Fetches SSH or GPG key from GitHub
  • gitlab:user.gpg: Fetches GPG key from GitLab

Caching Behavior:

  • Keys are cached in ~/.config/ascii-chat/acds_keys/<hostname>/
  • Cache invalidation requires user confirmation (prevents MITM attacks)
Parameters
acds_serverACDS server hostname (e.g., "acds.example.com")
key_specKey specification:
  • NULL: automatic trust for discovery-service.ascii-chat.com only
  • HTTPS URL: https://example.com/key.pub
  • File path: /path/to/key.pub or ~/.ssh/server.pub
  • GitHub: github:username
  • GitLab: gitlab:username.gpg
pubkey_outEd25519 public key output (32 bytes)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 275 of file discovery_keys.c.

275 {
276 if (!acds_server || !pubkey_out) {
277 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_verify");
278 }
279
280 uint8_t new_pubkey[32];
281 asciichat_error_t result;
282 bool is_official = is_official_server(acds_server);
283
284 // ===========================================================================
285 // Step 1: Obtain the public key
286 // ===========================================================================
287
288 if (!key_spec && is_official) {
289 // Automatic trust for official server: try SSH key first, then GPG
290 log_info("Attempting automatic HTTPS key trust for official ACDS server");
291
292 public_key_t key;
294 if (result != ASCIICHAT_OK) {
295 log_debug("SSH key download failed, trying GPG key");
297 }
298
299 if (result != ASCIICHAT_OK) {
300 return SET_ERRNO(ERROR_NETWORK, "Failed to download key from official ACDS server");
301 }
302
303 memcpy(new_pubkey, key.key, 32);
304
305 } else if (!key_spec) {
306 // No key_spec and not official server = error
308 "Third-party ACDS servers require explicit --discovery-service-key configuration."
309 "Only %s has automatic trust.",
311
312 } else {
313 // Use parse_public_key for all other cases (handles HTTPS, files, github:, gitlab:, etc.)
314 public_key_t key;
315 result = parse_public_key(key_spec, &key);
316 if (result != ASCIICHAT_OK) {
317 return SET_ERRNO(ERROR_CRYPTO_KEY, "Failed to load/download ACDS key from: %s", key_spec);
318 }
319
320 memcpy(new_pubkey, key.key, 32);
321 }
322
323 // ===========================================================================
324 // Step 2: Check cache and handle key changes
325 // ===========================================================================
326
327 uint8_t cached_pubkey[32];
328 result = discovery_keys_load_cached(acds_server, cached_pubkey);
329
330 if (result == ASCIICHAT_OK) {
331 // Cached key exists - compare
332 if (memcmp(cached_pubkey, new_pubkey, 32) != 0) {
333 // Key changed - require user verification
334 result = discovery_keys_verify_change(acds_server, cached_pubkey, new_pubkey);
335 if (result != ASCIICHAT_OK) {
336 return result; // User rejected or error
337 }
338
339 // User accepted - update cache
340 result = discovery_keys_save_cached(acds_server, new_pubkey);
341 if (result != ASCIICHAT_OK) {
342 log_warn("Failed to update cached key, continuing anyway");
343 }
344 } else {
345 log_debug("ACDS key matches cached key for: %s", acds_server);
346 }
347
348 } else {
349 // No cached key - save it for next time
350 log_info("First connection to ACDS server: %s, caching key", acds_server);
351 result = discovery_keys_save_cached(acds_server, new_pubkey);
352 if (result != ASCIICHAT_OK) {
353 log_warn("Failed to cache key, continuing anyway");
354 }
355 }
356
357 // ===========================================================================
358 // Step 3: Return verified key
359 // ===========================================================================
360
361 memcpy(pubkey_out, new_pubkey, 32);
362 log_debug("ACDS key verification successful for: %s", acds_server);
363 return ASCIICHAT_OK;
364}
asciichat_error_t discovery_keys_load_cached(const char *acds_server, uint8_t pubkey_out[32])
Check if cached key exists and load it.
asciichat_error_t discovery_keys_verify_change(const char *acds_server, const uint8_t old_pubkey[32], const uint8_t new_pubkey[32])
Verify key change with user.
asciichat_error_t discovery_keys_save_cached(const char *acds_server, const uint8_t pubkey[32])
Save key to cache.
#define ACDS_OFFICIAL_SERVER
Official ACDS server hostname (automatic HTTPS key trust)
#define ACDS_OFFICIAL_KEY_SSH_URL
Default HTTPS URLs for official ACDS keys.
#define ACDS_OFFICIAL_KEY_GPG_URL
@ ERROR_NETWORK
Definition error_codes.h:77
#define log_warn(...)
Log a WARN message.
Definition log/log.h:574
#define log_info(...)
Log an INFO message.
Definition log/log.h:561

References ACDS_OFFICIAL_KEY_GPG_URL, ACDS_OFFICIAL_KEY_SSH_URL, ACDS_OFFICIAL_SERVER, ASCIICHAT_OK, discovery_keys_load_cached(), discovery_keys_save_cached(), discovery_keys_verify_change(), ERROR_CRYPTO_KEY, ERROR_INVALID_PARAM, ERROR_NETWORK, public_key_t::key, log_debug, log_info, log_warn, parse_public_key(), and SET_ERRNO.

Referenced by client_crypto_init().

◆ discovery_keys_verify_change()

asciichat_error_t discovery_keys_verify_change ( const char *  acds_server,
const uint8_t  old_pubkey[32],
const uint8_t  new_pubkey[32] 
)

Verify key change with user.

When a cached key doesn't match the newly downloaded/loaded key, prompts the user to verify the change.

Displays:

  • Old key fingerprint (SHA256)
  • New key fingerprint (SHA256)
  • Warning about potential MITM attack
  • Prompt: "Accept new key? (y/N): "
Parameters
acds_serverACDS server hostname
old_pubkeyPrevious cached key (32 bytes)
new_pubkeyNew downloaded key (32 bytes)
Returns
ASCIICHAT_OK if user accepts, ERROR_USER_REJECTED if declined

Definition at line 233 of file discovery_keys.c.

234 {
235 if (!acds_server || !old_pubkey || !new_pubkey) {
236 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter in discovery_keys_verify_change");
237 }
238
239 char old_fingerprint[65], new_fingerprint[65];
240 compute_key_fingerprint(old_pubkey, old_fingerprint);
241 compute_key_fingerprint(new_pubkey, new_fingerprint);
242
243 const char *warning_msg = "\n"
244 "⚠️ WARNING: ACDS SERVER KEY HAS CHANGED\n"
245 "═══════════════════════════════════════════════════════════════\n"
246 "Server: %s\n"
247 "\n"
248 "Old key (SHA256): %s\n"
249 "New key (SHA256): %s\n"
250 "\n"
251 "This could indicate:\n"
252 " 1. The server operator rotated their key\n"
253 " 2. A man-in-the-middle attack is in progress\n"
254 "\n"
255 "Verify the new key fingerprint with the server operator before accepting.\n"
256 "═══════════════════════════════════════════════════════════════\n";
257
258 // Log to both stderr (via log_warn) and file log
259 log_warn(warning_msg, acds_server, old_fingerprint, new_fingerprint);
260
261 // Ask user to confirm
262 bool accepted = platform_prompt_yes_no("Accept new ACDS server key", false);
263 if (!accepted) {
264 return SET_ERRNO(ERROR_CRYPTO_VERIFICATION, "User rejected ACDS key change for: %s", acds_server);
265 }
266
267 log_info("User accepted ACDS key change for: %s", acds_server);
268 return ASCIICHAT_OK;
269}
@ ERROR_CRYPTO_VERIFICATION
bool platform_prompt_yes_no(const char *question, bool default_yes)
Prompt the user for a yes/no answer.
Definition util.c:83
void compute_key_fingerprint(const uint8_t key[ED25519_PUBLIC_KEY_SIZE], char fingerprint[CRYPTO_HEX_KEY_SIZE_NULL])

References ASCIICHAT_OK, compute_key_fingerprint(), ERROR_CRYPTO_VERIFICATION, ERROR_INVALID_PARAM, log_info, log_warn, platform_prompt_yes_no(), and SET_ERRNO.

Referenced by discovery_keys_verify().