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 llist_head entry;
|
||||
|
||||
uint8_t key[16];
|
||||
uint8_t key_present;
|
||||
char *token;
|
||||
int nr;
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
#include <osmocom/ctrl/control_cmd.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
||||
|
@ -993,11 +995,57 @@ static void ipaccess_close_bsc(void *data)
|
|||
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)
|
||||
{
|
||||
struct bsc_config *conf;
|
||||
const char *token = (const char *) TLVP_VAL(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) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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]);
|
||||
bsc->authenticated = 1;
|
||||
bsc->cfg = conf;
|
||||
|
@ -1227,9 +1284,9 @@ exit:
|
|||
if (msg->l2h[0] == IPAC_MSGT_ID_RESP && msgb_l2len(msg) > 2) {
|
||||
struct tlv_parsed tvp;
|
||||
int ret;
|
||||
ret = ipa_ccm_idtag_parse(&tvp,
|
||||
ret = ipa_ccm_idtag_parse_off(&tvp,
|
||||
(unsigned char *) msg->l2h + 2,
|
||||
msgb_l2len(msg) - 2);
|
||||
msgb_l2len(msg) - 2, 0);
|
||||
if (ret < 0) {
|
||||
LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
|
||||
"message with malformed TLVs\n");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* OpenBSC NAT interface to quagga VTY */
|
||||
/* (C) 2010-2013 by Holger Hans Peter Freyther
|
||||
* (C) 2010-2013 by On-Waves
|
||||
/* (C) 2010-2015 by Holger Hans Peter Freyther
|
||||
* (C) 2010-2015 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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, " 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);
|
||||
if (bsc->description)
|
||||
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;
|
||||
}
|
||||
|
||||
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>",
|
||||
"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);
|
||||
vty_install_default(NAT_BSC_NODE);
|
||||
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_no_lac_cmd);
|
||||
install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);
|
||||
|
|
Loading…
Reference in New Issue