buffer.c buffer.h \
cipher.h \
conf.c conf.h \
+ conf_net.c conf_net.h \
connection.c connection.h \
control.c control.h \
control_common.h \
fd_device.c \
graph.c graph.h \
hash.c hash.h \
+ keys.c keys.h \
have.h \
ipv4.h \
ipv6.h \
ifconfig.c ifconfig.h \
info.c info.h \
invitation.c invitation.h \
+ conf.c conf.h \
+ keys.c keys.h \
+ splay_tree.c splay_tree.h \
list.c list.h \
names.c names.h \
netutl.c netutl.h \
return false;
}
-bool get_config_subnet(const config_t *cfg, subnet_t **result) {
- subnet_t subnet = {0};
-
- if(!cfg) {
- return false;
- }
-
- if(!str2net(&subnet, cfg->value)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
- cfg->variable, cfg->file, cfg->line);
- return false;
- }
-
- if(subnetcheck(subnet)) {
- *(*result = new_subnet()) = subnet;
- return true;
- }
-
- logger(DEBUG_ALWAYS, LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
- cfg->variable, cfg->file, cfg->line);
- return false;
-}
-
/*
Read exactly one line and strip the trailing newline if any.
*/
}
void read_config_options(splay_tree_t *config_tree, const char *prefix) {
+ if(!cmdline_conf) {
+ return;
+ }
+
size_t prefix_len = prefix ? strlen(prefix) : 0;
for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) {
}
}
-bool read_server_config(void) {
+bool read_server_config(splay_tree_t *config_tree) {
char fname[PATH_MAX];
bool x;
extern bool get_config_int(const config_t *config, int *result);
extern bool get_config_string(const config_t *config, char **result);
extern bool get_config_address(const config_t *config, struct addrinfo **result);
-extern bool get_config_subnet(const config_t *config, struct subnet_t **result);
extern config_t *parse_config_line(char *line, const char *fname, int lineno);
extern bool read_config_file(splay_tree_t *config_tree, const char *filename, bool verbose);
extern void read_config_options(splay_tree_t *config_tree, const char *prefix);
-extern bool read_server_config(void);
+extern bool read_server_config(splay_tree_t *config_tree);
extern bool read_host_config(splay_tree_t *config_tree, const char *name, bool verbose);
extern bool append_config_file(const char *name, const char *key, const char *value);
--- /dev/null
+#include "conf_net.h"
+#include "logger.h"
+
+bool get_config_subnet(const config_t *cfg, subnet_t **result) {
+ subnet_t subnet = {0};
+
+ if(!cfg) {
+ return false;
+ }
+
+ if(!str2net(&subnet, cfg->value)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+ return false;
+ }
+
+ if(subnetcheck(subnet)) {
+ *(*result = new_subnet()) = subnet;
+ return true;
+ }
+
+ logger(DEBUG_ALWAYS, LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+ return false;
+}
+
--- /dev/null
+#ifndef TINC_NET_CONF_H
+#define TINC_NET_CONF_H
+
+#include "system.h"
+#include "conf.h"
+#include "subnet.h"
+
+extern bool get_config_subnet(const config_t *config, struct subnet_t **result);
+
+#endif // TINC_NET_CONF_H
--- /dev/null
+#include "system.h"
+#include "keys.h"
+#include "conf.h"
+#include "logger.h"
+#include "names.h"
+#include "xalloc.h"
+#include "ecdsa.h"
+#include "utils.h"
+
+bool disable_old_keys(const char *filename, const char *what) {
+ char tmpfile[PATH_MAX] = "";
+ char buf[1024];
+ bool disabled = false;
+ bool block = false;
+ bool error = false;
+
+ FILE *r = fopen(filename, "r");
+ FILE *w = NULL;
+
+ if(!r) {
+ return false;
+ }
+
+ int result = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename);
+
+ if(result < sizeof(tmpfile)) {
+ struct stat st = {.st_mode = 0600};
+ fstat(fileno(r), &st);
+ w = fopenmask(tmpfile, "w", st.st_mode);
+ }
+
+ while(fgets(buf, sizeof(buf), r)) {
+ if(!block && !strncmp(buf, "-----BEGIN ", 11)) {
+ if((strstr(buf, " ED25519 ") && strstr(what, "Ed25519")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) {
+ disabled = true;
+ block = true;
+ }
+ }
+
+ bool ed25519pubkey = !strncasecmp(buf, "Ed25519PublicKey", 16) && strchr(" \t=", buf[16]) && strstr(what, "Ed25519");
+
+ if(ed25519pubkey) {
+ disabled = true;
+ }
+
+ if(w) {
+ if(block || ed25519pubkey) {
+ fputc('#', w);
+ }
+
+ if(fputs(buf, w) < 0) {
+ error = true;
+ break;
+ }
+ }
+
+ if(block && !strncmp(buf, "-----END ", 9)) {
+ block = false;
+ }
+ }
+
+ if(w)
+ if(fclose(w) < 0) {
+ error = true;
+ }
+
+ if(ferror(r) || fclose(r) < 0) {
+ error = true;
+ }
+
+ if(disabled) {
+ if(!w || error) {
+ fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
+
+ if(w) {
+ unlink(tmpfile);
+ }
+
+ return false;
+ }
+
+#ifdef HAVE_MINGW
+ // We cannot atomically replace files on Windows.
+ char bakfile[PATH_MAX] = "";
+ snprintf(bakfile, sizeof(bakfile), "%s.bak", filename);
+
+ if(rename(filename, bakfile) || rename(tmpfile, filename)) {
+ rename(bakfile, filename);
+#else
+
+ if(rename(tmpfile, filename)) {
+#endif
+ fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
+ unlink(tmpfile);
+ return false;
+ }
+
+#ifdef HAVE_MINGW
+ unlink(bakfile);
+#endif
+ fprintf(stderr, "Warning: old key(s) found and disabled.\n");
+ }
+
+ unlink(tmpfile);
+ return true;
+}
+
+ecdsa_t *read_ecdsa_private_key(splay_tree_t *config_tree, char **keyfile) {
+ FILE *fp;
+ char *fname;
+
+ /* Check for PrivateKeyFile statement and read it */
+
+ if(!get_config_string(lookup_config(config_tree, "Ed25519PrivateKeyFile"), &fname)) {
+ xasprintf(&fname, "%s" SLASH "ed25519_key.priv", confbase);
+ }
+
+ fp = fopen(fname, "r");
+
+ if(!fp) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 private key file `%s': %s", fname, strerror(errno));
+
+ if(errno == ENOENT) {
+ logger(DEBUG_ALWAYS, LOG_INFO, "Create an Ed25519 key pair with `tinc -n %s generate-ed25519-keys'.", netname ? netname : ".");
+ }
+
+ free(fname);
+ return NULL;
+ }
+
+#ifndef HAVE_MINGW
+ struct stat s;
+
+ if(fstat(fileno(fp), &s)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat Ed25519 private key file `%s': %s'", fname, strerror(errno));
+ free(fname);
+ return false;
+ }
+
+ if(s.st_mode & ~0100700u) {
+ logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for Ed25519 private key file `%s'!", fname);
+ }
+
+#endif
+
+ ecdsa_t *key = ecdsa_read_pem_private_key(fp);
+ fclose(fp);
+
+ if(!key) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
+ free(fname);
+ return NULL;
+ }
+
+ if(keyfile) {
+ *keyfile = fname;
+ } else {
+ free(fname);
+ }
+
+ return key;
+}
+
+bool read_ecdsa_public_key(ecdsa_t **ecdsa, splay_tree_t **config_tree, const char *name) {
+ if(ecdsa_active(*ecdsa)) {
+ return true;
+ }
+
+ FILE *fp;
+ char *fname;
+ char *p;
+
+ if(!*config_tree) {
+ init_configuration(config_tree);
+
+ if(!read_host_config(*config_tree, name, true)) {
+ return false;
+ }
+ }
+
+ /* First, check for simple Ed25519PublicKey statement */
+
+ if(get_config_string(lookup_config(*config_tree, "Ed25519PublicKey"), &p)) {
+ *ecdsa = ecdsa_set_base64_public_key(p);
+ free(p);
+ return *ecdsa != NULL;
+ }
+
+ /* Else, check for Ed25519PublicKeyFile statement and read it */
+
+ if(!get_config_string(lookup_config(*config_tree, "Ed25519PublicKeyFile"), &fname)) {
+ xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ }
+
+ fp = fopen(fname, "r");
+
+ if(!fp) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 public key file `%s': %s",
+ fname, strerror(errno));
+ free(fname);
+ return false;
+ }
+
+ *ecdsa = ecdsa_read_pem_public_key(fp);
+
+ if(!*ecdsa && errno != ENOENT) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Parsing Ed25519 public key file `%s' failed.", fname);
+ }
+
+ fclose(fp);
+ free(fname);
+
+ return *ecdsa != NULL;
+}
+
+#ifndef DISABLE_LEGACY
+rsa_t *read_rsa_private_key(splay_tree_t *config_tree, char **keyfile) {
+ FILE *fp;
+ char *fname;
+ char *n, *d;
+ rsa_t *key;
+
+ /* First, check for simple PrivateKey statement */
+
+ config_t *rsa_priv_conf = lookup_config(config_tree, "PrivateKey");
+
+ if(get_config_string(rsa_priv_conf, &d)) {
+ if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "PrivateKey used but no PublicKey found!");
+ free(d);
+ return NULL;
+ }
+
+ key = rsa_set_hex_private_key(n, "FFFF", d);
+ free(n);
+ free(d);
+
+ if(key && keyfile && rsa_priv_conf->file) {
+ *keyfile = xstrdup(rsa_priv_conf->file);
+ }
+
+ return key;
+ }
+
+ /* Else, check for PrivateKeyFile statement and read it */
+
+ if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) {
+ xasprintf(&fname, "%s" SLASH "rsa_key.priv", confbase);
+ }
+
+ fp = fopen(fname, "r");
+
+ if(!fp) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s",
+ fname, strerror(errno));
+
+ if(errno == ENOENT) {
+ logger(DEBUG_ALWAYS, LOG_INFO, "Create an RSA key pair with `tinc -n %s generate-rsa-keys'.", netname ? netname : ".");
+ }
+
+ free(fname);
+ return NULL;
+ }
+
+#ifndef HAVE_MINGW
+ struct stat s;
+
+ if(fstat(fileno(fp), &s)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
+ free(fname);
+ return NULL;
+ }
+
+ if(s.st_mode & ~0100700u) {
+ logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
+ }
+
+#endif
+
+ key = rsa_read_pem_private_key(fp);
+ fclose(fp);
+
+ if(!key) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno));
+ free(fname);
+ return NULL;
+ }
+
+ if(keyfile) {
+ *keyfile = fname;
+ } else {
+ free(fname);
+ }
+
+ return key;
+}
+
+bool read_rsa_public_key(rsa_t **rsa, splay_tree_t *config_tree, const char *name) {
+ FILE *fp;
+ char *fname;
+ char *n;
+
+ /* First, check for simple PublicKey statement */
+
+ if(get_config_string(lookup_config(config_tree, "PublicKey"), &n)) {
+ *rsa = rsa_set_hex_public_key(n, "FFFF");
+ free(n);
+ return *rsa != NULL;
+ }
+
+ /* Else, check for PublicKeyFile statement and read it */
+
+ if(!get_config_string(lookup_config(config_tree, "PublicKeyFile"), &fname)) {
+ xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ }
+
+ fp = fopen(fname, "r");
+
+ if(!fp) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
+ free(fname);
+ return false;
+ }
+
+ *rsa = rsa_read_pem_public_key(fp);
+ fclose(fp);
+
+ if(!*rsa) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno));
+ }
+
+ free(fname);
+
+ return *rsa != NULL;
+}
+#endif
--- /dev/null
+#ifndef TINC_KEYS_H
+#define TINC_KEYS_H
+
+#include "rsa.h"
+#include "ecdsa.h"
+#include "splay_tree.h"
+
+extern bool disable_old_keys(const char *filename, const char *what);
+
+extern ecdsa_t *read_ecdsa_private_key(splay_tree_t *config_tree, char **keyfile);
+extern bool read_ecdsa_public_key(ecdsa_t **ecdsa, splay_tree_t **config_tree, const char *name);
+
+#ifndef DISABLE_LEGACY
+extern rsa_t *read_rsa_private_key(splay_tree_t *config, char **keyfile);
+extern bool read_rsa_public_key(rsa_t **rsa, splay_tree_t *config_tree, const char *name);
+#endif
+
+#endif // TINC_KEYS_H
#include "system.h"
#include "autoconnect.h"
+#include "conf_net.h"
#include "conf.h"
#include "connection.h"
#include "device.h"
exit_configuration(&config_tree);
init_configuration(&config_tree);
- if(!read_server_config()) {
+ if(!read_server_config(config_tree)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file.");
return EINVAL;
}
extern int main_loop(void);
extern void terminate_connection(struct connection_t *c, bool report);
extern bool node_read_ecdsa_public_key(struct node_t *n);
-extern bool read_ecdsa_public_key(struct connection_t *c);
-extern bool read_rsa_public_key(struct connection_t *c);
extern void handle_device_data(void *data, int flags);
extern void handle_meta_connection_data(struct connection_t *c);
extern void regenerate_key(void);
#include "system.h"
#include "cipher.h"
+#include "conf_net.h"
#include "conf.h"
#include "connection.h"
#include "control.h"
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
+#include "keys.h"
#ifdef HAVE_MINIUPNPC
#include "upnp.h"
return n->ecdsa;
}
-bool read_ecdsa_public_key(connection_t *c) {
- if(ecdsa_active(c->ecdsa)) {
- return true;
- }
-
- FILE *fp;
- char *fname;
- char *p;
-
- if(!c->config_tree) {
- init_configuration(&c->config_tree);
-
- if(!read_host_config(c->config_tree, c->name, true)) {
- return false;
- }
- }
-
- /* First, check for simple Ed25519PublicKey statement */
-
- if(get_config_string(lookup_config(c->config_tree, "Ed25519PublicKey"), &p)) {
- c->ecdsa = ecdsa_set_base64_public_key(p);
- free(p);
- return c->ecdsa;
- }
-
- /* Else, check for Ed25519PublicKeyFile statement and read it */
-
- if(!get_config_string(lookup_config(c->config_tree, "Ed25519PublicKeyFile"), &fname)) {
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
- }
-
- fp = fopen(fname, "r");
-
- if(!fp) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 public key file `%s': %s",
- fname, strerror(errno));
- free(fname);
- return false;
- }
-
- c->ecdsa = ecdsa_read_pem_public_key(fp);
-
- if(!c->ecdsa && errno != ENOENT) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Parsing Ed25519 public key file `%s' failed.", fname);
- }
-
- fclose(fp);
- free(fname);
- return c->ecdsa;
-}
-
-#ifndef DISABLE_LEGACY
-bool read_rsa_public_key(connection_t *c) {
- FILE *fp;
- char *fname;
- char *n;
-
- /* First, check for simple PublicKey statement */
-
- if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) {
- c->rsa = rsa_set_hex_public_key(n, "FFFF");
- free(n);
- return c->rsa;
- }
-
- /* Else, check for PublicKeyFile statement and read it */
-
- if(!get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) {
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
- }
-
- fp = fopen(fname, "r");
-
- if(!fp) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
- free(fname);
- return false;
- }
-
- c->rsa = rsa_read_pem_public_key(fp);
- fclose(fp);
-
- if(!c->rsa) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno));
- }
-
- free(fname);
- return c->rsa;
-}
-#endif
-
-static bool read_ecdsa_private_key(void) {
- FILE *fp;
- char *fname;
-
- /* Check for PrivateKeyFile statement and read it */
-
- if(!get_config_string(lookup_config(config_tree, "Ed25519PrivateKeyFile"), &fname)) {
- xasprintf(&fname, "%s" SLASH "ed25519_key.priv", confbase);
- }
-
- fp = fopen(fname, "r");
-
- if(!fp) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 private key file `%s': %s", fname, strerror(errno));
-
- if(errno == ENOENT) {
- logger(DEBUG_ALWAYS, LOG_INFO, "Create an Ed25519 key pair with `tinc -n %s generate-ed25519-keys'.", netname ? netname : ".");
- }
-
- free(fname);
- return false;
- }
-
-#ifndef HAVE_MINGW
- struct stat s;
-
- if(fstat(fileno(fp), &s)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat Ed25519 private key file `%s': %s'", fname, strerror(errno));
- free(fname);
- return false;
- }
-
- if(s.st_mode & ~0100700u) {
- logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for Ed25519 private key file `%s'!", fname);
- }
-
-#endif
-
- myself->connection->ecdsa = ecdsa_read_pem_private_key(fp);
- fclose(fp);
-
- if(!myself->connection->ecdsa) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
- }
-
- free(fname);
- return myself->connection->ecdsa;
-}
-
static bool read_invitation_key(void) {
FILE *fp;
char fname[PATH_MAX];
return invitation_key;
}
-#ifndef DISABLE_LEGACY
-static bool read_rsa_private_key(void) {
- FILE *fp;
- char *fname;
- char *n, *d;
-
- /* First, check for simple PrivateKey statement */
-
- if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) {
- if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "PrivateKey used but no PublicKey found!");
- free(d);
- return false;
- }
-
- myself->connection->rsa = rsa_set_hex_private_key(n, "FFFF", d);
- free(n);
- free(d);
- return myself->connection->rsa;
- }
-
- /* Else, check for PrivateKeyFile statement and read it */
-
- if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) {
- xasprintf(&fname, "%s" SLASH "rsa_key.priv", confbase);
- }
-
- fp = fopen(fname, "r");
-
- if(!fp) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s",
- fname, strerror(errno));
-
- if(errno == ENOENT) {
- logger(DEBUG_ALWAYS, LOG_INFO, "Create an RSA key pair with `tinc -n %s generate-rsa-keys'.", netname ? netname : ".");
- }
-
- free(fname);
- return false;
- }
-
-#ifndef HAVE_MINGW
- struct stat s;
-
- if(fstat(fileno(fp), &s)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
- free(fname);
- return false;
- }
-
- if(s.st_mode & ~0100700u) {
- logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
- }
-
-#endif
-
- myself->connection->rsa = rsa_read_pem_private_key(fp);
- fclose(fp);
-
- if(!myself->connection->rsa) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno));
- }
-
- free(fname);
- return myself->connection->rsa;
-}
-#endif
-
#ifndef DISABLE_LEGACY
static timeout_t keyexpire_timeout;
myself->options |= PROT_MINOR << 24;
#ifdef DISABLE_LEGACY
- experimental = read_ecdsa_private_key();
+ myself->connection->ecdsa = read_ecdsa_private_key(config_tree, NULL);
+ experimental = myself->connection->ecdsa != NULL;
if(!experimental) {
logger(DEBUG_ALWAYS, LOG_ERR, "No private key available, cannot start tinc!");
#else
if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
- experimental = read_ecdsa_private_key();
+ myself->connection->ecdsa = read_ecdsa_private_key(config_tree, NULL);
+ experimental = myself->connection->ecdsa != NULL;
if(!experimental) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Support for SPTPS disabled.");
}
} else {
- if(experimental && !read_ecdsa_private_key()) {
- return false;
+ if(experimental) {
+ myself->connection->ecdsa = read_ecdsa_private_key(config_tree, NULL);
+
+ if(!myself->connection->ecdsa) {
+ return false;
+ }
}
}
- if(!read_rsa_private_key()) {
+ myself->connection->rsa = read_rsa_private_key(config_tree, NULL);
+
+ if(!myself->connection->rsa) {
if(experimental) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Support for legacy protocol disabled.");
} else {
#include "xalloc.h"
#include "ed25519/sha512.h"
+#include "keys.h"
int invitation_lifetime;
ecdsa_t *invitation_key = NULL;
int minor = 0;
if(experimental) {
- if(c->outgoing && !read_ecdsa_public_key(c)) {
+ if(c->outgoing && !read_ecdsa_public_key(&c->ecdsa, &c->config_tree, c->name)) {
minor = 1;
} else {
minor = myself->connection->protocol_minor;
}
if(experimental) {
- read_ecdsa_public_key(c);
+ read_ecdsa_public_key(&c->ecdsa, &c->config_tree, c->name);
}
/* Ignore failures if no key known yet */
return false;
}
- if(!read_rsa_public_key(c)) {
+ if(!read_rsa_public_key(&c->rsa, c->config_tree, c->name)) {
return false;
}
return false;
}
- if(ecdsa_active(c->ecdsa) || read_ecdsa_public_key(c)) {
+ if(ecdsa_active(c->ecdsa) || read_ecdsa_public_key(&c->ecdsa, &c->config_tree, c->name)) {
char *knownkey = ecdsa_get_base64_public_key(c->ecdsa);
bool different = strcmp(knownkey, pubkey);
free(knownkey);
#include "top.h"
#include "version.h"
#include "subnet.h"
+#include "keys.h"
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
return true;
}
-/* Open a file with the desired permissions, minus the umask.
- Also, if we want to create an executable file, we call fchmod()
- to set the executable bits. */
-
-FILE *fopenmask(const char *filename, const char *mode, mode_t perms) {
- mode_t mask = umask(0);
- perms &= ~mask;
- umask(~perms & 0777);
- FILE *f = fopen(filename, mode);
-
- if(!f) {
- fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
- return NULL;
- }
-
-#ifdef HAVE_FCHMOD
-
- if((perms & 0444) && f) {
- fchmod(fileno(f), perms);
- }
-
-#endif
- umask(mask);
- return f;
-}
-
-static void disable_old_keys(const char *filename, const char *what) {
- char tmpfile[PATH_MAX] = "";
- char buf[1024];
- bool disabled = false;
- bool block = false;
- bool error = false;
-
- FILE *r = fopen(filename, "r");
- FILE *w = NULL;
-
- if(!r) {
- return;
- }
-
- int result = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename);
-
- if(result < sizeof(tmpfile)) {
- struct stat st = {.st_mode = 0600};
- fstat(fileno(r), &st);
- w = fopenmask(tmpfile, "w", st.st_mode);
- }
-
- while(fgets(buf, sizeof(buf), r)) {
- if(!block && !strncmp(buf, "-----BEGIN ", 11)) {
- if((strstr(buf, " ED25519 ") && strstr(what, "Ed25519")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) {
- disabled = true;
- block = true;
- }
- }
-
- bool ed25519pubkey = !strncasecmp(buf, "Ed25519PublicKey", 16) && strchr(" \t=", buf[16]) && strstr(what, "Ed25519");
-
- if(ed25519pubkey) {
- disabled = true;
- }
-
- if(w) {
- if(block || ed25519pubkey) {
- fputc('#', w);
- }
-
- if(fputs(buf, w) < 0) {
- error = true;
- break;
- }
- }
-
- if(block && !strncmp(buf, "-----END ", 9)) {
- block = false;
- }
- }
-
- if(w)
- if(fclose(w) < 0) {
- error = true;
- }
-
- if(ferror(r) || fclose(r) < 0) {
- error = true;
- }
-
- if(disabled) {
- if(!w || error) {
- fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
-
- if(w) {
- unlink(tmpfile);
- }
-
- return;
- }
-
-#ifdef HAVE_MINGW
- // We cannot atomically replace files on Windows.
- char bakfile[PATH_MAX] = "";
- snprintf(bakfile, sizeof(bakfile), "%s.bak", filename);
-
- if(rename(filename, bakfile) || rename(tmpfile, filename)) {
- rename(bakfile, filename);
-#else
-
- if(rename(tmpfile, filename)) {
-#endif
- fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
- } else {
-#ifdef HAVE_MINGW
- unlink(bakfile);
-#endif
- fprintf(stderr, "Warning: old key(s) found and disabled.\n");
- }
- }
-
- unlink(tmpfile);
-}
-
static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
FILE *r;
char directory[PATH_MAX] = ".";
exit_fail:
free_names();
- free(cmdline_conf);
+ list_delete_list(cmdline_conf);
cmdline_conf = NULL;
return false;
}
exit_configuration(&config_tree);
}
- free(cmdline_conf);
+ list_delete_list(cmdline_conf);
free_names();
}
srand(now.tv_sec + now.tv_usec);
crypto_init();
- if(!read_server_config()) {
+ if(!read_server_config(config_tree)) {
return 1;
}
return ret_name;
}
+
+/* Open a file with the desired permissions, minus the umask.
+ Also, if we want to create an executable file, we call fchmod()
+ to set the executable bits. */
+
+FILE *fopenmask(const char *filename, const char *mode, mode_t perms) {
+ mode_t mask = umask(0);
+ perms &= ~mask;
+ umask(~perms & 0777);
+ FILE *f = fopen(filename, mode);
+
+ if(!f) {
+ fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+#ifdef HAVE_FCHMOD
+
+ if((perms & 0444) && f) {
+ fchmod(fileno(f), perms);
+ }
+
+#endif
+ umask(mask);
+ return f;
+}
+
extern bool check_netname(const char *netname, bool strict);
char *replace_name(const char *name);
+extern FILE *fopenmask(const char *filename, const char *mode, mode_t perms);
+
#endif