nat: After we identified the bsc check the key
We are using the token to find the right bsc_config and then we can use the last_rand of the bsc_connection to calculate the expected result and try to compare it with a time constant(???) memcmp.
This commit is contained in:
parent
e2ac6b77fe
commit
694d98042f
|
@ -148,6 +148,8 @@ enum bsc_cfg_ctr {
|
||||||
struct bsc_config {
|
struct bsc_config {
|
||||||
struct llist_head entry;
|
struct llist_head entry;
|
||||||
|
|
||||||
|
uint8_t key[16];
|
||||||
|
uint8_t key_present;
|
||||||
char *token;
|
char *token;
|
||||||
int nr;
|
int nr;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#include <osmocom/ctrl/control_cmd.h>
|
#include <osmocom/ctrl/control_cmd.h>
|
||||||
#include <osmocom/ctrl/control_if.h>
|
#include <osmocom/ctrl/control_if.h>
|
||||||
|
|
||||||
|
#include <osmocom/crypt/auth.h>
|
||||||
|
|
||||||
#include <osmocom/core/application.h>
|
#include <osmocom/core/application.h>
|
||||||
#include <osmocom/core/talloc.h>
|
#include <osmocom/core/talloc.h>
|
||||||
|
|
||||||
|
@ -993,11 +995,57 @@ static void ipaccess_close_bsc(void *data)
|
||||||
bsc_close_connection(conn);
|
bsc_close_connection(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wishful thinking to generate a constant time compare */
|
||||||
|
static int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count)
|
||||||
|
{
|
||||||
|
int x = 0, i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
x |= exp[i] ^ rel[i];
|
||||||
|
|
||||||
|
return x != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, const uint8_t *key, const int keylen)
|
||||||
|
{
|
||||||
|
struct osmo_auth_vector vec;
|
||||||
|
|
||||||
|
struct osmo_sub_auth_data auth = {
|
||||||
|
.type = OSMO_AUTH_TYPE_GSM,
|
||||||
|
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* expect a specific keylen */
|
||||||
|
if (keylen != 8) {
|
||||||
|
LOGP(DNAT, LOGL_ERROR, "Key length is wrong: %d for bsc nr %d\n",
|
||||||
|
keylen, conf->nr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(auth.u.umts.opc, conf->key, 16);
|
||||||
|
memcpy(auth.u.umts.k, conf->key, 16);
|
||||||
|
memset(auth.u.umts.amf, 0, 2);
|
||||||
|
auth.u.umts.sqn = 0;
|
||||||
|
|
||||||
|
memset(&vec, 0, sizeof(vec));
|
||||||
|
osmo_auth_gen_vec(&vec, &auth, conn->last_rand);
|
||||||
|
|
||||||
|
if (vec.res_len != 8) {
|
||||||
|
LOGP(DNAT, LOGL_ERROR, "Res length is wrong: %d for bsc nr %d\n",
|
||||||
|
keylen, conf->nr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return constant_time_cmp(vec.res, key, 8) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
|
static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
|
||||||
{
|
{
|
||||||
struct bsc_config *conf;
|
struct bsc_config *conf;
|
||||||
const char *token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
|
const char *token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
|
||||||
int len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
|
int len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
|
||||||
|
const uint8_t *xres = TLVP_VAL(tvp, 0x24);
|
||||||
|
const int xlen = TLVP_LEN(tvp, 0x24);
|
||||||
|
|
||||||
if (bsc->cfg) {
|
if (bsc->cfg) {
|
||||||
LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
|
LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
|
||||||
|
@ -1033,6 +1081,15 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We have set a key and expect it to be present */
|
||||||
|
if (conf->key_present && !verify_key(bsc, conf, xres, xlen - 1)) {
|
||||||
|
LOGP(DNAT, LOGL_ERROR,
|
||||||
|
"Wrong key for bsc nr %d fd: %d.\n", conf->nr,
|
||||||
|
bsc->write_queue.bfd.fd);
|
||||||
|
bsc_close_connection(bsc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rate_ctr_inc(&conf->stats.ctrg->ctr[BCFG_CTR_NET_RECONN]);
|
rate_ctr_inc(&conf->stats.ctrg->ctr[BCFG_CTR_NET_RECONN]);
|
||||||
bsc->authenticated = 1;
|
bsc->authenticated = 1;
|
||||||
bsc->cfg = conf;
|
bsc->cfg = conf;
|
||||||
|
@ -1227,9 +1284,9 @@ exit:
|
||||||
if (msg->l2h[0] == IPAC_MSGT_ID_RESP && msgb_l2len(msg) > 2) {
|
if (msg->l2h[0] == IPAC_MSGT_ID_RESP && msgb_l2len(msg) > 2) {
|
||||||
struct tlv_parsed tvp;
|
struct tlv_parsed tvp;
|
||||||
int ret;
|
int ret;
|
||||||
ret = ipa_ccm_idtag_parse(&tvp,
|
ret = ipa_ccm_idtag_parse_off(&tvp,
|
||||||
(unsigned char *) msg->l2h + 2,
|
(unsigned char *) msg->l2h + 2,
|
||||||
msgb_l2len(msg) - 2);
|
msgb_l2len(msg) - 2, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
|
LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
|
||||||
"message with malformed TLVs\n");
|
"message with malformed TLVs\n");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* OpenBSC NAT interface to quagga VTY */
|
/* OpenBSC NAT interface to quagga VTY */
|
||||||
/* (C) 2010-2013 by Holger Hans Peter Freyther
|
/* (C) 2010-2015 by Holger Hans Peter Freyther
|
||||||
* (C) 2010-2013 by On-Waves
|
* (C) 2010-2015 by On-Waves
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -151,6 +151,8 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
|
||||||
{
|
{
|
||||||
vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
|
vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
|
||||||
vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
|
vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
|
||||||
|
if (bsc->key_present)
|
||||||
|
vty_out(vty, " auth-key %s%s", osmo_hexdump(bsc->key, 16), VTY_NEWLINE);
|
||||||
dump_lac(vty, &bsc->lac_list);
|
dump_lac(vty, &bsc->lac_list);
|
||||||
if (bsc->description)
|
if (bsc->description)
|
||||||
vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
|
vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
|
||||||
|
@ -814,6 +816,30 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN",
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_bsc_auth_key, cfg_bsc_auth_key_cmd,
|
||||||
|
"auth-key KEY",
|
||||||
|
"Authentication (secret) key configuration\n"
|
||||||
|
"Non null security key\n")
|
||||||
|
{
|
||||||
|
struct bsc_config *conf = vty->index;
|
||||||
|
|
||||||
|
memset(conf->key, 0, sizeof(conf->key));
|
||||||
|
osmo_hexparse(argv[0], conf->key, sizeof(conf->key));
|
||||||
|
conf->key_present = 1;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_bsc_no_auth_key, cfg_bsc_no_auth_key_cmd,
|
||||||
|
"no auth-key",
|
||||||
|
NO_STR "Authentication (secret) key configuration\n")
|
||||||
|
{
|
||||||
|
struct bsc_config *conf = vty->index;
|
||||||
|
|
||||||
|
memset(conf->key, 0, sizeof(conf->key));
|
||||||
|
conf->key_present = 0;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
|
DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
|
||||||
"Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
|
"Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
|
||||||
{
|
{
|
||||||
|
@ -1202,6 +1228,8 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
|
||||||
install_node(&bsc_node, config_write_bsc);
|
install_node(&bsc_node, config_write_bsc);
|
||||||
vty_install_default(NAT_BSC_NODE);
|
vty_install_default(NAT_BSC_NODE);
|
||||||
install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
|
install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
|
||||||
|
install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd);
|
||||||
|
install_element(NAT_BSC_NODE, &cfg_bsc_no_auth_key_cmd);
|
||||||
install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd);
|
install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd);
|
||||||
install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd);
|
install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd);
|
||||||
install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);
|
install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);
|
||||||
|
|
Loading…
Reference in New Issue