&& conMap.find(identifier) == conMap.end()
&& isAcceptNewConnections.load()) {
// is receiving as server, connection did not already exist
+ int authPolicy = this->authPolicy.load();
+ if(pktType == 1 && !flags.test(2)
+ && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+ UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+ "Client peer ",
+ UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+ " port ",
+ ntohs(receivedData.sin6_port),
+ " attempted connection with packet authentication "
+ "enabled, but auth is disabled and AuthPolicy is STRICT");
+ return;
+ } else if(pktType == 0 && flags.test(2)
+ && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+ UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+ "Client peer ",
+ UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+ " port ",
+ ntohs(receivedData.sin6_port),
+ " attempted connection with packet authentication "
+ "disabled, but auth is enabled and AuthPolicy is STRICT");
+ return;
+ }
unsigned char *sk = nullptr;
unsigned char *pk = nullptr;
if(keysSet.load()) {
", port ", ntohs(receivedData.sin6_port));
return;
}
+ int authPolicy = this->authPolicy.load();
+ if(pktType == 2 && !iter->second.flags.test(6)
+ && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+ // This block actually should never happen, because the server
+ // receives a packet first. If client requests without auth,
+ // then the server will either deny connection (if strict) or
+ // fallback to a connection without auth (if fallback).
+ UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+ "Server peer ",
+ UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+ " port ",
+ ntohs(receivedData.sin6_port),
+ " attempted connection with packet authentication "
+ "enabled, but auth is disabled and AuthPolicy is STRICT");
+ return;
+ } else if(pktType == 0 && iter->second.flags.test(6)
+ && authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
+ UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
+ "Server peer ",
+ UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
+ " port ",
+ ntohs(receivedData.sin6_port),
+ " attempted connection with packet authentication "
+ "disabled, but auth is enabled and AuthPolicy is STRICT");
+ return;
+ }
if(pktType == 2 && flags.test(2) && iter->second.flags.test(6)) {
#ifdef UDPC_LIBSODIUM_ENABLED
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
"peer is not using libsodium, but peer_pk was "
"pre-set, dropping to no-verification mode");
- // TODO set policy for using/not-using libsodium
}
}
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium) {
UDPC::Context *ctx = new UDPC::Context(false);
ctx->flags.set(1, isClient != 0);
+ ctx->authPolicy.exchange(UDPC_AuthPolicy::UDPC_AUTH_POLICY_FALLBACK);
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Got listen addr ",
UDPC_atostr((UDPC_HContext)ctx, listenId.addr));
return 1;
}
+int UDPC_get_auth_policy(UDPC_HContext ctx) {
+ UDPC::Context *c = UDPC::verifyContext(ctx);
+ if(!c) {
+ return 0;
+ }
+
+ return c->authPolicy.load();
+}
+
+int UDPC_set_auth_policy(UDPC_HContext ctx, int policy) {
+ UDPC::Context *c = UDPC::verifyContext(ctx);
+ if(!c) {
+ return 0;
+ }
+
+ bool isInRange = false;
+ for(int i = 0; i < UDPC_AuthPolicy::UDPC_AUTH_POLICY_SIZE; ++i) {
+ if(policy == i) {
+ isInRange = true;
+ break;
+ }
+ }
+ if(!isInRange) {
+ return 0;
+ }
+
+ return c->authPolicy.exchange(policy);
+}
+
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
return UDPC_atostr(ctx, connectionId.addr);
}
struct UDPC_Context;
typedef struct UDPC_Context *UDPC_HContext;
-typedef enum { UDPC_SILENT, UDPC_ERROR, UDPC_WARNING, UDPC_INFO, UDPC_VERBOSE, UDPC_DEBUG } UDPC_LoggingType;
+typedef enum {
+ UDPC_SILENT,
+ UDPC_ERROR,
+ UDPC_WARNING,
+ UDPC_INFO,
+ UDPC_VERBOSE,
+ UDPC_DEBUG
+} UDPC_LoggingType;
+
+typedef enum {
+ UDPC_AUTH_POLICY_FALLBACK=0,
+ UDPC_AUTH_POLICY_STRICT,
+ UDPC_AUTH_POLICY_SIZE /// Used internally to get max size of enum
+} UDPC_AuthPolicy;
/*!
* \brief Data identifying a peer via addr, port, and scope_id
int UDPC_unset_libsodium_keys(UDPC_HContext ctx);
+int UDPC_get_auth_policy(UDPC_HContext ctx);
+int UDPC_set_auth_policy(UDPC_HContext ctx, int value);
+
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_IPV6_ADDR_TYPE addr);
#include <string.h>
#include <stdio.h>
#include <threads.h>
+#include <assert.h>
#ifdef UDPC_LIBSODIUM_ENABLED
#include <sodium.h>
puts("-ls - enable libsodium");
puts("-ck <pubkey_file> - connect to server expecting this public key");
puts("-sk <pubkey> <seckey> - start with pub/sec key pair");
+ puts("-p <\"fallback\" or \"strict\"> - set auth policy");
}
void sleep_seconds(unsigned int seconds) {
const char *seckey_file = NULL;
unsigned char pubkey[crypto_sign_PUBLICKEYBYTES];
unsigned char seckey[crypto_sign_SECRETKEYBYTES];
+ int authPolicy = UDPC_AUTH_POLICY_FALLBACK;
+
while(argc > 0) {
if(strcmp(argv[0], "-c") == 0) {
isClient = 1;
pubkey_file = argv[0];
--argc; ++argv;
seckey_file = argv[0];
+ } else if(strcmp(argv[0], "-p") == 0 && argc > 1) {
+ if(strcmp(argv[1], "fallback") == 0) {
+ authPolicy = UDPC_AUTH_POLICY_FALLBACK;
+ --argc; ++argv;
+ } else if(strcmp(argv[1], "strict") == 0) {
+ authPolicy = UDPC_AUTH_POLICY_STRICT;
+ --argc; ++argv;
+ } else {
+ printf("ERROR: invalid argument \"%s %s\"\n", argv[0], argv[1]);
+ usage();
+ return 1;
+ }
} else {
printf("ERROR: invalid argument \"%s\"\n", argv[0]);
usage();
puts("Set pubkey/seckey for server");
}
+ UDPC_set_auth_policy(context, authPolicy);
+ assert(UDPC_get_auth_policy(context) == authPolicy);
+ if(authPolicy == UDPC_AUTH_POLICY_FALLBACK) {
+ puts("Auth policy set to \"fallback\"");
+ } else if(authPolicy == UDPC_AUTH_POLICY_STRICT) {
+ puts("Auth policy set to \"strict\"");
+ }
+
UDPC_enable_threaded_update(context);
unsigned int tick = 0;