From 5236fb03afecd3d7a6ec6e96712c79a31be32132 Mon Sep 17 00:00:00 2001 From: Ondrej Filip Date: Sat, 26 Jun 2004 20:11:14 +0000 Subject: [PATCH] Password management redesigned (untested). --- nest/config.Y | 82 ++++++++++++++++++++++++++++++++------------ nest/password.c | 63 +++++++--------------------------- nest/password.h | 15 +++++---- proto/rip/auth.c | 84 ++++++++++++++++++++++------------------------ proto/rip/config.Y | 2 +- proto/rip/rip.c | 3 -- proto/rip/rip.h | 2 +- 7 files changed, 122 insertions(+), 129 deletions(-) diff --git a/nest/config.Y b/nest/config.Y index 4f9b46b6..7a83a60a 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -11,18 +11,21 @@ CF_HDR #include "nest/rt-dev.h" #include "nest/password.h" #include "nest/cmds.h" +#include "lib/lists.h" CF_DEFINES static struct proto_config *this_proto; static struct iface_patt *this_ipatt; +static list *this_p_list; +static struct password_item *this_p_item; CF_DECLS CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) -CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREIMPORT) +CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREIMPORT, GENERATE) CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE) @@ -33,7 +36,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT) %type idval %type imexport %type rtable -%type

password_list password_begin +%type

password_list password_begin password_begin_list %type optsym %type r_args %type echo_mask echo_size debug_mask debug_list debug_flag import_or_proto @@ -193,36 +196,71 @@ debug_flag: /* Password lists */ -password_begin: +password_items: + /* empty */ + | password_item ';' password_items +; + +password_item: + password_item_begin '{' password_item_params '}' + | password_item_begin +; + +password_item_begin: PASSWORD TEXT { - last_password_item = cfg_alloc(sizeof (struct password_item)); - last_password_item->password = $2; - last_password_item->from = 0; - last_password_item->to = TIME_INFINITY; - last_password_item->id = 0; - last_password_item->next = NULL; - $$=last_password_item; + static int id = 0; + this_p_item = cfg_alloc(sizeof (struct password_item)); + this_p_item->password = $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 = id++; + add_tail(this_p_list, &this_p_item->n); } - ; +; -password_items: +password_item_params: /* empty */ { } - | FROM datetime password_items { last_password_item->from = $2; } - | TO datetime password_items { last_password_item->to = $2; } - | PASSIVE datetime password_items { last_password_item->passive = $2; } - | ID expr password_items { last_password_item->id = $2; } + | GENERATE FROM datetime ';' password_item_params { this_p_item->genfrom = $3; } + | GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; } + | ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; } + | ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; } + | ID expr ';' password_item_params { this_p_item->id = $2; } ; -password_list: - /* empty */ { $$ = NULL; } - | password_begin password_items ';' password_list { - $1->next = $4; +password_list: + password_begin_list '{' password_items '}' { $$ = $1; } - ; + | password_begin +; + +password_begin_list: + PASSWORDS { + this_p_list = cfg_alloc(sizeof(list)); + init_list(this_p_list); + $$ = this_p_list; + } +; + +password_begin: + PASSWORD TEXT { + this_p_list = cfg_alloc(sizeof(list)); + init_list(this_p_list); + this_p_item = cfg_alloc(sizeof (struct password_item)); + this_p_item->password = $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 = 0; + add_tail(this_p_list, &this_p_item->n); + $$ = this_p_list; + } +; /* Core commands */ - CF_CLI_HELP(SHOW, ..., [[Show status information]]) CF_CLI(SHOW STATUS,,, [[Show router status]]) diff --git a/nest/password.c b/nest/password.c index 594569cc..63096023 100644 --- a/nest/password.c +++ b/nest/password.c @@ -1,7 +1,8 @@ /* * BIRD -- Password handling * - * Copyright 1999 Pavel Machek + * (c) 1999 Pavel Machek + * (c) 2004 Ondrej Filip * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -12,62 +13,22 @@ struct password_item *last_password_item = NULL; -static int -password_goodness(struct password_item *i) -{ - if (i->from > now) - return 0; - if (i->to < now) - return 0; - if (i->passive < now) - return 1; - return 2; -} - struct password_item * -get_best_password(struct password_item *head, int flags UNUSED) +password_find(list *l) { - int good = -1; - struct password_item *best = NULL; + struct password_item *pi; - while (head) { - int cur = password_goodness(head); - if (cur > good) { - good = cur; - best = head; - } - head=head->next; + WALK_LIST(pi, *l) + { + if ((pi->genfrom > now) && (pi->gento < now)) + return pi; } - return best; + return NULL; } -void -password_strncpy(char *to, char *from, int len) +void password_cpy(char *dst, char *src, int size) { - int i; - for (i=0; ifrom != new->from || - old->to != new->to || - old->passive != new->passive || - old->id != new->id || - strcmp(old->password, new->password)) - return 0; - old = old->next; - new = new->next; - } -} diff --git a/nest/password.h b/nest/password.h index 481eeb61..0c453836 100644 --- a/nest/password.h +++ b/nest/password.h @@ -1,7 +1,8 @@ /* * BIRD -- Password handling * - * Copyright 1999 Pavel Machek + * (c) 1999 Pavel Machek + * (c) 2004 Ondrej Filip * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -10,18 +11,18 @@ #define PASSWORD_H #include "lib/timer.h" +#define MD5_AUTH_SIZE 16 + struct password_item { - struct password_item *next; + node n; char *password; int id; - bird_clock_t from, passive, to; + bird_clock_t accfrom, accto, genfrom, gento; }; extern struct password_item *last_password_item; -struct password_item *get_best_password(struct password_item *head, int flags); -extern int password_same(struct password_item *, struct password_item *); -extern void password_strncpy(char *to, char *from, int len); - +struct password_item *password_find(list *); +void password_cpy(char *dst, char *src, int size); #endif diff --git a/proto/rip/auth.c b/proto/rip/auth.c index 3d4b91c8..bc0cc4b1 100644 --- a/proto/rip/auth.c +++ b/proto/rip/auth.c @@ -2,6 +2,7 @@ * Rest in pieces - RIP protocol * * Copyright (c) 1999 Pavel Machek + * Copyright (c) 2004 Ondrej Filip * * Bug fixes by Eric Leblond , April 2003 * @@ -38,7 +39,7 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru switch (ntohs(block->authtype)) { /* Authentication type */ case AT_PLAINTEXT: { - struct password_item *passwd = get_best_password( P_CF->passwords, 0 ); + struct password_item *passwd = password_find(P_CF->passwords); DBG( "Plaintext passwd" ); if (!passwd) { log( L_AUTH "No passwords set and password authentication came" ); @@ -50,12 +51,18 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru return 1; } } - return 0; + break; case AT_MD5: DBG( "md5 password" ); { - struct password_item *head; + struct password_item *pass = NULL, *ptmp; struct rip_md5_tail *tail; + struct MD5Context ctxt; + char md5sum_packet[16]; + char md5sum_computed[16]; + struct neighbor *neigh = neigh_find(p, &whotoldme, 0); + list *l = P_CF->passwords; + if (ntohs(block->packetlen) != PACKETLEN(num) - sizeof(struct rip_md5_tail) ) { log( L_ERR "Packet length in MD5 does not match computed value" ); return 1; @@ -67,44 +74,34 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru return 1; } - head = P_CF->passwords; - while (head) { - DBG( "time, " ); - if ((head->from > now) || (head->to < now)) - goto skip; - if (block->seq) { - struct neighbor *neigh = neigh_find(p, &whotoldme, 0); - if (!neigh) { - log( L_AUTH "Non-neighbour MD5 checksummed packet?" ); - } else { - if (neigh->aux > block->seq) { - log( L_AUTH "MD5 protected packet with lower numbers" ); - return 0; - } - neigh->aux = block->seq; - } - } - DBG( "check, " ); - if (head->id == block->keyid) { - struct MD5Context ctxt; - char md5sum_packet[16]; - char md5sum_computed[16]; - - memset(md5sum_packet,0,16); - memcpy(md5sum_packet, tail->md5, 16); - password_strncpy(tail->md5, head->password, 16); - - MD5Init(&ctxt); - MD5Update(&ctxt, (char *) packet, ntohs(block->packetlen) + sizeof(struct rip_block_auth) ); - MD5Final(md5sum_computed, &ctxt); - if (memcmp(md5sum_packet, md5sum_computed, 16)) - return 1; - return 0; - } - skip: - head = head->next; + WALK_LIST(ptmp, *l) + { + if (block->keyid != pass->id) continue; + if ((pass->genfrom > now) || (pass->gento < now)) continue; + pass = ptmp; + break; } - return 1; + + if(!pass) return 1; + + if (!neigh) { + log( L_AUTH "Non-neighbour MD5 checksummed packet?" ); + } else { + if (neigh->aux > block->seq) { + log( L_AUTH "MD5 protected packet with lower numbers" ); + return 1; + } + neigh->aux = block->seq; + } + + memcpy(md5sum_packet, tail->md5, 16); + password_cpy(tail->md5, pass->password, 16); + + MD5Init(&ctxt); + MD5Update(&ctxt, (char *) packet, ntohs(block->packetlen) + sizeof(struct rip_block_auth) ); + MD5Final(md5sum_computed, &ctxt); + if (memcmp(md5sum_packet, md5sum_computed, 16)) + return 1; } } @@ -118,7 +115,7 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru int rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num ) { - struct password_item *passwd = get_best_password( P_CF->passwords, 0 ); + struct password_item *passwd = password_find( P_CF->passwords); if (!P_CF->authtype) return PACKETLEN(num); @@ -134,7 +131,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru block->mustbeFFFF = 0xffff; switch (P_CF->authtype) { case AT_PLAINTEXT: - password_strncpy( (char *) (&block->packetlen), passwd->password, 16); + password_cpy( (char *) (&block->packetlen), passwd->password, 16); return PACKETLEN(num); case AT_MD5: { @@ -159,8 +156,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru tail->mustbeFFFF = 0xffff; tail->mustbe0001 = 0x0100; - memset(tail->md5,0,16); - password_strncpy( tail->md5, passwd->password, 16 ); + password_cpy(tail->md5, passwd->password, 16); MD5Init(&ctxt); MD5Update(&ctxt, (char *) packet, PACKETLEN(num) + sizeof(struct rip_md5_tail)); MD5Final(tail->md5, &ctxt); diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 00d68f78..4a352c66 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -51,7 +51,7 @@ rip_cfg: | rip_cfg GARBAGE TIME expr ';' { RIP_CFG->garbage_time = $4; } | rip_cfg TIMEOUT TIME expr ';' { RIP_CFG->timeout_time = $4; } | rip_cfg AUTHENTICATION rip_auth ';' {RIP_CFG->authtype = $3; } - | rip_cfg PASSWORDS '{' password_list '}' {RIP_CFG->passwords = $4; } + | rip_cfg password_list ';' {RIP_CFG->passwords = $2; } | rip_cfg HONOR ALWAYS ';' { RIP_CFG->honor = HO_ALWAYS; } | rip_cfg HONOR NEIGHBOR ';' { RIP_CFG->honor = HO_NEIGHBOR; } | rip_cfg HONOR NEVER ';' { RIP_CFG->honor = HO_NEVER; } diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 8c7b37c6..05525e95 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -981,9 +981,6 @@ rip_reconfigure(struct proto *p, struct proto_config *c) if (!iface_patts_equal(&P_CF->iface_list, &new->iface_list, (void *) rip_pat_compare)) return 0; - if (!password_same(P_CF->passwords, - new->passwords)) - return 0; return !memcmp(((byte *) P_CF) + generic, ((byte *) new) + generic, sizeof(struct rip_proto_config) - generic); diff --git a/proto/rip/rip.h b/proto/rip/rip.h index e01a4bdb..5a6e36d8 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -121,7 +121,7 @@ struct rip_patt { struct rip_proto_config { struct proto_config c; list iface_list; /* Patterns configured -- keep it first; see rip_reconfigure why */ - struct password_item *passwords; /* Passwords, keep second */ + list *passwords; /* Passwords, keep second */ int infinity; /* User configurable data; must be comparable with memcmp */ int port;