Nest: Allow specifying security keys as hex bytes as well as strings
Add support for specifying a password in hexadecimal format, The result is the same whether a password is specified as a quoted string or a hex-encoded byte string, this just makes it more convenient to input high-entropy byte strings as MAC keys.
This commit is contained in:
parent
f1a824190c
commit
35f88b305a
7 changed files with 93 additions and 18 deletions
|
@ -255,6 +255,37 @@ WHITE [ \t]
|
|||
return IP4;
|
||||
}
|
||||
|
||||
{XIGIT}{2}(:{XIGIT}{2}|{XIGIT}{2}){15,} {
|
||||
char *s = yytext;
|
||||
size_t len = 0, i;
|
||||
struct bytestring *bytes;
|
||||
byte *b;
|
||||
|
||||
while (*s) {
|
||||
len++;
|
||||
s += 2;
|
||||
if (*s == ':')
|
||||
s++;
|
||||
}
|
||||
bytes = cfg_allocz(sizeof(*bytes) + len);
|
||||
|
||||
bytes->length = len;
|
||||
b = &bytes->data[0];
|
||||
s = yytext;
|
||||
errno = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
*b = bstrtobyte16(s);
|
||||
if (errno == ERANGE)
|
||||
cf_error("Invalid hex string");
|
||||
b++;
|
||||
s += 2;
|
||||
if (*s == ':')
|
||||
s++;
|
||||
}
|
||||
cf_lval.bs = bytes;
|
||||
return BYTESTRING;
|
||||
}
|
||||
|
||||
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
|
||||
if (!ip6_pton(yytext, &cf_lval.ip6))
|
||||
cf_error("Invalid IPv6 address %s", yytext);
|
||||
|
|
|
@ -136,6 +136,11 @@ struct sym_scope {
|
|||
int active; /* Currently entered */
|
||||
};
|
||||
|
||||
struct bytestring {
|
||||
size_t length;
|
||||
byte data[];
|
||||
};
|
||||
|
||||
#define SYM_MAX_LEN 64
|
||||
|
||||
/* Remember to update cf_symbol_class_name() */
|
||||
|
|
|
@ -92,6 +92,7 @@ CF_DECLS
|
|||
struct channel_limit cl;
|
||||
struct timeformat *tf;
|
||||
mpls_label_stack *mls;
|
||||
struct bytestring *bs;
|
||||
}
|
||||
|
||||
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
|
||||
|
@ -103,6 +104,7 @@ CF_DECLS
|
|||
%token <i64> VPN_RD
|
||||
%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED
|
||||
%token <t> TEXT
|
||||
%token <bs> BYTESTRING
|
||||
%type <iface> ipa_scope
|
||||
|
||||
%type <i> expr bool pxlen4
|
||||
|
|
|
@ -776,7 +776,7 @@ agreement").
|
|||
protocol packets are processed in the local TX queues. This option is
|
||||
Linux specific. Default value is 7 (highest priority, privileged traffic).
|
||||
|
||||
<tag><label id="proto-pass">password "<m/password/" [ { <m>password options</m> } ]</tag>
|
||||
<tag><label id="proto-pass">password "<m/password/" | <m/hex_key/ [ { <m>password options</m> } ] </tag>
|
||||
Specifies a password that can be used by the protocol as a shared secret
|
||||
key. Password option can be used more times to specify more passwords.
|
||||
If more passwords are specified, it is a protocol-dependent decision
|
||||
|
@ -784,6 +784,11 @@ agreement").
|
|||
authentication is enabled, authentication can be enabled by separate,
|
||||
protocol-dependent <cf/authentication/ option.
|
||||
|
||||
A password can also be specified as a hexadecimal key. <m/hex_key/ is a
|
||||
sequence of hexadecimal digit pairs, optionally colon-separated. A key
|
||||
specified this way must be at least 16 bytes (32 digits) long (although
|
||||
specific algorithms can impose other restrictions).
|
||||
|
||||
This option is allowed in BFD, OSPF and RIP protocols. BGP has also
|
||||
<cf/password/ option, but it is slightly different and described
|
||||
separately.
|
||||
|
|
|
@ -26,6 +26,7 @@ void buffer_puts(buffer *buf, const char *str);
|
|||
|
||||
u64 bstrtoul10(const char *str, char **end);
|
||||
u64 bstrtoul16(const char *str, char **end);
|
||||
byte bstrtobyte16(const char *str);
|
||||
|
||||
int patmatch(const byte *pat, const byte *str);
|
||||
|
||||
|
|
|
@ -59,3 +59,30 @@ bstrtoul16(const char *str, char **end)
|
|||
errno = ERANGE;
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
byte
|
||||
bstrtobyte16(const char *str)
|
||||
{
|
||||
byte out = 0;
|
||||
for (int i=0; i<2; i++) {
|
||||
switch (str[i]) {
|
||||
case '0' ... '9':
|
||||
out *= 16;
|
||||
out += str[i] - '0';
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
out *= 16;
|
||||
out += str[i] + 10 - 'a';
|
||||
break;
|
||||
case 'A' ... 'F':
|
||||
out *= 16;
|
||||
out += str[i] + 10 - 'A';
|
||||
break;
|
||||
default:
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,25 @@ iface_patt_check(void)
|
|||
cf_error("Interface name/mask expected, not IP prefix");
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_password(const void *key, uint length, uint id)
|
||||
{
|
||||
if (!this_p_list) {
|
||||
this_p_list = cfg_allocz(sizeof(list));
|
||||
init_list(this_p_list);
|
||||
password_id = 1;
|
||||
}
|
||||
this_p_item = cfg_allocz(sizeof (struct password_item));
|
||||
this_p_item->password = key;
|
||||
this_p_item->length = length;
|
||||
this_p_item->genfrom = 0;
|
||||
this_p_item->gento = TIME_INFINITY;
|
||||
this_p_item->accfrom = 0;
|
||||
this_p_item->accto = TIME_INFINITY;
|
||||
this_p_item->id = id;
|
||||
this_p_item->alg = ALG_UNDEFINED;
|
||||
add_tail(this_p_list, &this_p_item->n);
|
||||
}
|
||||
|
||||
static inline void
|
||||
reset_passwords(void)
|
||||
|
@ -490,23 +509,8 @@ password_item:
|
|||
;
|
||||
|
||||
password_item_begin:
|
||||
PASSWORD text {
|
||||
if (!this_p_list) {
|
||||
this_p_list = cfg_allocz(sizeof(list));
|
||||
init_list(this_p_list);
|
||||
password_id = 1;
|
||||
}
|
||||
this_p_item = cfg_allocz(sizeof(struct password_item));
|
||||
this_p_item->password = $2;
|
||||
this_p_item->length = strlen($2);
|
||||
this_p_item->genfrom = 0;
|
||||
this_p_item->gento = TIME_INFINITY;
|
||||
this_p_item->accfrom = 0;
|
||||
this_p_item->accto = TIME_INFINITY;
|
||||
this_p_item->id = password_id++;
|
||||
this_p_item->alg = ALG_UNDEFINED;
|
||||
add_tail(this_p_list, &this_p_item->n);
|
||||
}
|
||||
PASSWORD text { init_password($2, strlen($2), password_id++); }
|
||||
| PASSWORD BYTESTRING { init_password($2->data, $2->length, password_id++); }
|
||||
;
|
||||
|
||||
password_item_params:
|
||||
|
|
Loading…
Reference in a new issue