diff --git a/doc/ManagementAPI.md b/doc/ManagementAPI.md index 07130ad..617e345 100644 --- a/doc/ManagementAPI.md +++ b/doc/ManagementAPI.md @@ -183,4 +183,6 @@ affect the availability of the n2n networking. Therefore the machine readable API include an authentication component. Currently, the only authentication is a simple password that the client -must provide. +must provide. It defaults to 'n2n' and can manually be set through the +command line parameter `--management-password ` – for edge as well +as for supernode. diff --git a/edge.8 b/edge.8 index 5d30fde..7a81444 100644 --- a/edge.8 +++ b/edge.8 @@ -102,7 +102,7 @@ use header encryption, supernode needs fixed community \fB\-z1\fR ... \fB\-z2\fR compress outgoing data packets, -z1 = lzo1x, disabled by default .TP -\fB\--select-rtt\fR +\fB\-\-select-rtt\fR select supernode by round trip time if several to choose from (federation), defaults to load-based selection strategy if not provided. .SH TAP DEVICE AND OVERLAY NETWORK CONFIGURATION @@ -186,6 +186,11 @@ binds the edge management system to the given UDP port. Default 5644. Use this if you need to run multiple instance of edge; or something is bound to that port. .TP +\fB\-\-management-password \fR<\fIpassword\fR> +sets the password for access to JSON API at the management port, defaults to 'n2n'. The password +has to be provided when using 'scripts/n2n-ctl', 'scripts/n2n-httpd' or for any other relevant +access to JSON API at the management port. +.TP \fB\-v\fR, \fB\-\-verbose\fR make more verbose, repeat as required .TP diff --git a/include/n2n_define.h b/include/n2n_define.h index bf7f55a..cdee5da 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -126,6 +126,9 @@ enum n2n_mgmt_type { N2N_MGMT_WRITE = 1, }; +#define N2N_MGMT_PASSWORD "n2n" /* default password for management port access (so far, json only) */ + + #define N2N_TCP_BACKLOG_QUEUE_SIZE 3 /* number of concurrently pending connections to be accepted */ /* NOT the number of max. TCP connections */ diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index 26bbb27..2715731 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -675,6 +675,7 @@ typedef struct n2n_edge_conf { int metric; /**< Network interface metric (Windows only). */ uint8_t sn_selection_strategy; /**< encodes currently chosen supernode selection strategy. */ uint8_t number_max_sn_pings; /**< Number of maximum concurrently allowed supernode pings. */ + uint64_t mgmt_password_hash; /**< contains hash of managament port password. */ } n2n_edge_conf_t; @@ -836,6 +837,7 @@ typedef struct n2n_sn { uint32_t dynamic_key_time; /* UTC time of last dynamic key generation (second accuracy) */ uint8_t override_spoofing_protection; /* set if overriding MAC/IP spoofing protection (cli option '-M') */ n2n_resolve_parameter_t *resolve_parameter;/*Pointer to name resolver's parameter block */ + uint64_t mgmt_password_hash;/* contains hash of managament port password */ } n2n_sn_t; diff --git a/src/edge.c b/src/edge.c index c1aef2c..01e2096 100644 --- a/src/edge.c +++ b/src/edge.c @@ -206,6 +206,8 @@ static void help (int level) { "[-f] " #endif "[-t ] " + "[--management-password ] " + "\n " "[-v] " "[-n ] " #ifndef WIN32 @@ -325,6 +327,8 @@ static void help (int level) { #endif printf(" -t | management UDP port, for multiple edges on a machine,\n" " | defaults to %u\n", N2N_EDGE_MGMT_PORT); + printf(" --management_... | management port password, defaults to '%s'\n" + " ...password | \n", N2N_MGMT_PASSWORD); printf(" -v | make more verbose, repeat as required\n"); printf(" -n | route an IPv4 network via the gateway, use 0.0.0.0/0 for\n" " | the default gateway, can be set multiple times\n"); @@ -733,6 +737,12 @@ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *e break; } + case ']': /* password for management port */ { + conf->mgmt_password_hash = pearson_hash_64((uint8_t*)optargument, strlen(optargument)); + + break; + } + case 'h': /* quick reference */ { return 2; } @@ -779,15 +789,16 @@ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *e static const struct option long_options[] = { - { "community", required_argument, NULL, 'c' }, - { "supernode-list", required_argument, NULL, 'l' }, - { "tap-device", required_argument, NULL, 'd' }, - { "euid", required_argument, NULL, 'u' }, - { "egid", required_argument, NULL, 'g' }, - { "verbose", no_argument, NULL, 'v' }, - { "help", no_argument, NULL, '@' }, /* internal special character '@' to identify long help case */ - { "select-rtt", no_argument, NULL, '[' }, /* '[' rtt selection strategy */ - { NULL, 0, NULL, 0 } + { "community", required_argument, NULL, 'c' }, + { "supernode-list", required_argument, NULL, 'l' }, + { "tap-device", required_argument, NULL, 'd' }, + { "euid", required_argument, NULL, 'u' }, + { "egid", required_argument, NULL, 'g' }, + { "verbose", no_argument, NULL, 'v' }, + { "help", no_argument, NULL, '@' }, /* internal special character '@' to identify long help case */ + { "select-rtt", no_argument, NULL, '[' }, /* '[' rtt selection strategy */ + { "management-password", required_argument, NULL, ']' }, /* ']' management port password */ + { NULL, 0, NULL, 0 } }; /* *************************************************** */ diff --git a/src/edge_management.c b/src/edge_management.c index 9f28339..5438ae3 100644 --- a/src/edge_management.c +++ b/src/edge_management.c @@ -325,18 +325,20 @@ static void mgmt_help (n2n_edge_t *eee, char *udp_buf, const struct sockaddr_in * Reads are not dangerous, so they are simply allowed * Writes are possibly dangerous, so they need a fake password */ -static int mgmt_auth (const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *auth, char *argv0, char *argv) { +static int mgmt_auth (n2n_edge_t *eee, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *auth, char *argv0, char *argv) { + if(auth) { /* If we have an auth key, it must match */ - if(0 == strcmp(auth,"CHANGEME")) { + if(eee->conf.mgmt_password_hash == pearson_hash_64((uint8_t*)auth, strlen(auth))) { return 1; } return 0; } /* if we dont have an auth key, we can still read */ - if(type==N2N_MGMT_READ) { + if(type == N2N_MGMT_READ) { return 1; } + return 0; } @@ -414,7 +416,7 @@ void handleMgmtJson (n2n_edge_t *eee, char *udp_buf, const struct sockaddr_in se auth = NULL; } - if(!mgmt_auth(sender_sock, type, auth, argv0, argv)) { + if(!mgmt_auth(eee, sender_sock, type, auth, argv0, argv)) { mgmt_error(eee, udp_buf, sender_sock, tag, "badauth"); return; } diff --git a/src/edge_utils.c b/src/edge_utils.c index 23d192a..781f460 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -3670,6 +3670,8 @@ static void edge_cleanup_routes (n2n_edge_t *eee) { void edge_init_conf_defaults (n2n_edge_conf_t *conf) { + char *tmp_string; + memset(conf, 0, sizeof(*conf)); conf->bind_address = INADDR_ANY; /* any address */ @@ -3701,6 +3703,13 @@ void edge_init_conf_defaults (n2n_edge_conf_t *conf) { generate_private_key(*(conf->shared_secret), getenv("N2N_PASSWORD")); } + tmp_string = calloc(1, strlen(N2N_MGMT_PASSWORD) + 1); + if(tmp_string) { + strncpy((char*)tmp_string, N2N_MGMT_PASSWORD, strlen(N2N_MGMT_PASSWORD) + 1); + conf->mgmt_password_hash = pearson_hash_64((uint8_t*)tmp_string, strlen(N2N_MGMT_PASSWORD)); + free(tmp_string); + } + conf->sn_selection_strategy = SN_SELECTION_STRATEGY_LOAD; conf->metric = 0; } diff --git a/src/sn_management.c b/src/sn_management.c index bde2daf..0f34a39 100644 --- a/src/sn_management.c +++ b/src/sn_management.c @@ -309,18 +309,20 @@ static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in se * Reads are not dangerous, so they are simply allowed * Writes are possibly dangerous, so they need a fake password */ -static int mgmt_auth (const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *auth, char *argv0, char *argv) { +static int mgmt_auth (n2n_sn_t *sss, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *auth, char *argv0, char *argv) { + if(auth) { /* If we have an auth key, it must match */ - if(0 == strcmp(auth,"CHANGEME")) { + if(sss->mgmt_password_hash == pearson_hash_64((uint8_t*)auth, strlen(auth))) { return 1; } return 0; } /* if we dont have an auth key, we can still read */ - if(type==N2N_MGMT_READ) { + if(type == N2N_MGMT_READ) { return 1; } + return 0; } @@ -398,7 +400,7 @@ void handleMgmtJson_sn (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in s auth = NULL; } - if(!mgmt_auth(sender_sock, type, auth, argv0, argv)) { + if(!mgmt_auth(sss, sender_sock, type, auth, argv0, argv)) { mgmt_error(sss, udp_buf, sender_sock, tag, "badauth"); return; } diff --git a/src/sn_utils.c b/src/sn_utils.c index ab812d0..40d6746 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -730,6 +730,9 @@ int comm_init (struct sn_community *comm, char *cmn) { /** Initialise the supernode structure */ int sn_init_defaults (n2n_sn_t *sss) { + + char *tmp_string; + #ifdef WIN32 initWin32(); #endif @@ -786,6 +789,13 @@ int sn_init_defaults (n2n_sn_t *sss) { sss->mac_addr[0] &= ~0x01; /* Clear multicast bit */ sss->mac_addr[0] |= 0x02; /* Set locally-assigned bit */ + tmp_string = calloc(1, strlen(N2N_MGMT_PASSWORD) + 1); + if(tmp_string) { + strncpy((char*)tmp_string, N2N_MGMT_PASSWORD, strlen(N2N_MGMT_PASSWORD) + 1); + sss->mgmt_password_hash = pearson_hash_64((uint8_t*)tmp_string, strlen(N2N_MGMT_PASSWORD)); + free(tmp_string); + } + return 0; /* OK */ } diff --git a/src/supernode.c b/src/supernode.c index 31158ce..7266aab 100644 --- a/src/supernode.c +++ b/src/supernode.c @@ -80,6 +80,8 @@ static void help (int level) { "[-f] " #endif "[-t ] " + "\n " + "[--management-password ] " "[-v] " #ifndef WIN32 "\n " @@ -138,6 +140,8 @@ static void help (int level) { #endif printf(" -t | management UDP port, for multiple supernodes on a machine,\n" " | defaults to %u\n", N2N_SN_MGMT_PORT); + printf(" --management_... | management port password, defaults to '%s'\n" + " ...password | \n", N2N_MGMT_PASSWORD); printf(" -v | make more verbose, repeat as required\n"); #ifndef WIN32 printf(" -u | numeric user ID to use when privileges are dropped\n"); @@ -303,6 +307,12 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { if(sss->community_file) strcpy(sss->community_file, _optarg); break; + + case ']': /* password for management port */ { + sss->mgmt_password_hash = pearson_hash_64((uint8_t*)_optarg, strlen(_optarg)); + + break; + } #if defined(N2N_HAVE_DAEMON) case 'f': /* foreground */ sss->daemon = 0; @@ -330,16 +340,17 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { /* *********************************************** */ static const struct option long_options[] = { - {"communities", required_argument, NULL, 'c'}, + {"communities", required_argument, NULL, 'c'}, #if defined(N2N_HAVE_DAEMON) - {"foreground", no_argument, NULL, 'f'}, + {"foreground", no_argument, NULL, 'f'}, #endif - {"local-port", required_argument, NULL, 'p'}, - {"mgmt-port", required_argument, NULL, 't'}, - {"autoip", required_argument, NULL, 'a'}, - {"help", no_argument, NULL, '@'}, /* special character '@' to identify long help case */ - {"verbose", no_argument, NULL, 'v'}, - {NULL, 0, NULL, 0} + {"local-port", required_argument, NULL, 'p'}, + {"mgmt-port", required_argument, NULL, 't'}, + {"autoip", required_argument, NULL, 'a'}, + {"verbose", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, '@'}, /* special character '@' to identify long help case */ + {"management-password", required_argument, NULL, ']' }, /* ']' management port password */ + {NULL, 0, NULL, 0} }; /* *************************************************** */ diff --git a/supernode.1 b/supernode.1 index 7243ed2..742b826 100644 --- a/supernode.1 +++ b/supernode.1 @@ -67,6 +67,10 @@ disable daemon mode (UNIX) and run in foreground. \fB\-t \fR<\fIport\fR>, \fB\-\-mgmt-port\fR=<\fIport\fR> management UDP port, for multiple supernodes on a machine, defaults to 5645 .TP +\fB\-\-management-password \fR<\fIpassword\fR> +sets the password for access to JSON API at the management port, defaults to 'n2n'. The password +has to be provided for relevant access to JSON API at the management port. +.TP \fB\-v\fR, \fB\-\-verbose\fR use verbose logging .TP