📄 mn_reg.c
字号:
keyreq->length = htons(4); /* FIX: mn_spi is the SPI that MN will assign for the security * association; this may need to be uniquely selected for some * cases(?) */ keyreq->mn_spi = htonl(1000); pos += GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq); left -= GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq); } if (add_mn_aaa_auth_ext && config.use_aaa) { /* add MN-AAA authentication extension */ if (left < sizeof(struct generalized_auth_ext) + MAX_SK_LEN) return -1; DEBUG(DEBUG_MESSAGES, " * gen_auth_ext(MN-AAA)\n"); n = auth_add_gen(config.mn_aaa_auth_alg, config.mn_aaa_shared_secret, config.mn_aaa_shared_secret_len, (unsigned char *) start, challenge != NULL ? MSG_CHALLENGE_EXT_DATA(challenge) : NULL, challenge != NULL ? GET_CHALLENGE_LEN(challenge) : 0, (struct generalized_auth_ext *) pos, GENERALIZED_AUTH_MN_AAA, htonl(config.mn_aaa_spi)); pos += n; left -= n; } mn.prev_req_replied = 0; return (int) (pos - orig);}/* send_registration: * @request_type: * REG_DISC - deregistration * REG_CONNECT - normal connection request * REG_REREG - reregistration (do not send sk_auth extension * and ask full time) * * Send registration message. * * Returns: 0 on success, -1 on error. */int send_registration(int request_type){ char sendbuf[MAXMSG]; char *pos; /* pointer to next byte to write in sendbuf */ int n, len; struct sockaddr_in addr; int use_reverse; struct msg_extensions ext; if (MAXMSG < (sizeof(struct reg_req) + 2 * (sizeof(struct msg_auth) + 16))) { DEBUG(DEBUG_INFO, "MN: send_reg: too small send buffer!"); return -1; } use_reverse = config.tunneling_mode == TUNMODE_AUTO_REVERSE || config.tunneling_mode == TUNMODE_REVERSE; if (mn.current_adv != NULL) { if (mn.current_adv->addr.s_addr != mn.fa_addr.s_addr) { DEBUG(DEBUG_INFO, "fa_addr=%s != ", inet_ntoa(mn.fa_addr)); DEBUG(DEBUG_INFO, "current_adv->addr=%s\n", inet_ntoa(mn.current_adv->addr)); } DEBUG(DEBUG_INFO, "Setting in_use=%i for FA %s (send reg)\n", request_type == REG_DISC ? 0 : 1, inet_ntoa(mn.current_adv->addr)); mn.current_adv->in_use = request_type == REG_DISC ? 0 : 1; if (config.tunneling_mode == TUNMODE_AUTO_REVERSE && (ntohs(mn.current_adv->adv.ext->opts) & AGENT_ADV_BIDIR_TUNNELING) == 0) use_reverse = 0; if (config.tunneling_mode == TUNMODE_AUTO_TRIANGLE && mn.current_adv->adv.own_ext != NULL && (mn.current_adv->adv.own_ext->opts & AGENT_ADV_OWN_TRIANGLE_TUNNELING) == 0) use_reverse = 1; } else { DEBUG(DEBUG_INFO, "send_registration: current_adv == NULL!?\n"); } if ((use_reverse && config.tunneling_mode == TUNMODE_TRIANGLE) || (!use_reverse && config.tunneling_mode == TUNMODE_REVERSE)) { DEBUG(DEBUG_INFO, "FA does not support wanted tunneling mode -" " aborting registration\n"); if (mn.current_adv != NULL) mn.current_adv->reg_failed = 1; return -1; } if (use_reverse) DEBUG(DEBUG_MESSAGES, "Requesting reverse tunneling\n"); pos = sendbuf; DEBUG(DEBUG_MESSAGES, "Sending registration message:\n * header\n"); n = fill_req_header(pos, request_type, use_reverse); if (n < 0) return -1; pos += n; n = add_req_extensions(pos, MAXMSG - n, sendbuf, request_type, use_reverse); if (n < 0) { LOG2(LOG_ERR, "Registration request buffer overflow - unable" " to send the request\n"); return -1; } pos += n; len = (int) (pos - sendbuf); assert(len <= MAXMSG); /* call parse_msg() to parse the message in order to get the details * of the sent message into debug output; in addition, this validates * the format of the request */ if (parse_msg(sendbuf, len, &ext) != 0) { DEBUG(DEBUG_INFO, "WARNING! Own registration request was not " "valid!\n"); } /* add ARP entry, if not already added */ if (mn.current_adv != NULL && mn.current_adv->adv_type == MN_ADV_TYPE_FA && !mn.current_adv->arpentry) { struct sockaddr hwaddr; DEBUG(DEBUG_INFO, "Adding ARP entry for FA\n"); memset(&hwaddr, 0, sizeof(hwaddr)); hwaddr.sa_family = ARPHRD_ETHER;#ifdef DYN_TARGET_LINUX memcpy(hwaddr.sa_data, mn.current_adv->adv.from.sll_addr, mn.current_adv->adv.from.sll_halen);#else memcpy(hwaddr.sa_data, mn.current_adv->adv.eth->h_source, ETH_ALEN);#endif if (arp_add_permanent_item(mn.current_adv->addr, mn.current_adv->ifname, &hwaddr) < 0) { LOG2(LOG_WARNING, "arp_add_permanent_item(%s, %s, %s) " "failed\n", inet_ntoa(mn.current_adv->addr), mn.current_adv->ifname, ether_hwtoa((unsigned char *)hwaddr.sa_data)); } mn.current_adv->arpentry = 1; } /* add host route to FA, if not already added */ if (config.enable_fa_decapsulation && mn.current_adv != NULL && mn.current_adv->adv_type == MN_ADV_TYPE_FA && !mn.current_adv->routeentry) { DEBUG(DEBUG_INFO, "Adding routing entry for FA\n"); add_fa_host_route(mn.current_adv->ifname, mn.agentadv, mn.current_adv->ifindex, mn.fa_addr); } /* send the message */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = mn.fa_addr.s_addr; addr.sin_port = htons(config.udp_port); DEBUG(DEBUG_MESSAGES, "sending registration request to %s:%i, " "type=%i\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), request_type); gettimeofday(&mn.last_reg_send_time, NULL); DEBUG(DEBUG_TIMERS, "last_reg_send_time=%li.%06li (FA=%s)\n", mn.last_reg_send_time.tv_sec, mn.last_reg_send_time.tv_usec, inet_ntoa(addr.sin_addr)); n = sendto(mn.registration_socket, sendbuf, len, 0, (struct sockaddr *) &addr, sizeof(addr)); if (n == len) { /* store id for reply */ mn.registration_id[0] = ntohl(((struct reg_req *)sendbuf)->id[0]); mn.registration_id[1] = ntohl(((struct reg_req *)sendbuf)->id[1]); /* set registration time */ gettimeofday(&timers[TIMER_REQUEST], NULL); mn.last_request_sent = timers[TIMER_REQUEST].tv_sec; return 0; } else { LOG2(LOG_ERR, "send_reg - sendto: %s\n", strerror(errno)); return -1; }}static void show_key_dump(const char *title, const unsigned char *key, int keylen){ int i; DEBUG(DEBUG_INFO, "%s: ", title); for (i = 0; i < keylen; i++) DEBUG(DEBUG_INFO, "%02x", key[i]); DEBUG(DEBUG_INFO, "\n");}/** * handle_reply_aaa: * @ext: parsed registration reply extensions * * Handle AAA related extensions: validate the reply and generate MN-FA and/or * MN-HA security association if key material was present. * * Returns: 1 = valid extensions, 0 = invalid extensions */static int handle_reply_aaa(struct msg_extensions *ext, struct in_addr addr){ unsigned char *nodeaddr; unsigned int nodeaddrlen; unsigned char fa_secret[MAXSHAREDSECRETLEN]; int fa_secret_len; unsigned char ha_secret[MAXSHAREDSECRETLEN]; int ha_secret_len; struct mn_fa_key_material_from_aaa *fa_key = NULL; struct mn_ha_key_material_from_aaa *ha_key = NULL; if (config.mn_home_ip_addr.s_addr == 0 && config.mn_nai_len > 0) { nodeaddr = config.mn_nai; nodeaddrlen = config.mn_nai_len; } else { nodeaddr = (unsigned char *) &config.mn_home_ip_addr; nodeaddrlen = 4; } if (!config.use_aaa) { DEBUG(DEBUG_INFO, "Registration reply has key material from " "AAA, but AAA is not configured; ignoring extension\n"); ext->mn_fa_key_material_aaa = NULL; ext->mn_ha_key_material_aaa = NULL; return 1; } if (ext->mn_fa_key_material_aaa) { fa_key = (struct mn_fa_key_material_from_aaa *) (ext->mn_fa_key_material_aaa + 1); if (ext->mf_auth == NULL || !auth_is_protected(ext->mn_fa_key_material_aaa, ext->mf_auth)) { LOG2(LOG_ALERT, "MN-FA auth. ext. does not protect " "MN-FA key material from AAA\n"); return 0; } /* generate MN-FA key from key material */ fa_secret_len = MAXSHAREDSECRETLEN; if (auth_generate_key( config.mn_aaa_keygen_alg, config.mn_aaa_shared_secret, config.mn_aaa_shared_secret_len, (unsigned char *) (fa_key + 1), GET_GEN_MN_FA_KEY_REP_LEN( ext->mn_fa_key_material_aaa) - sizeof(struct mn_fa_key_material_from_aaa), nodeaddr, nodeaddrlen, fa_secret, &fa_secret_len)) { LOG2(LOG_ALERT, "MN-FA key generation with material " "from AAA failed\n"); return 0; } show_key_dump("MN-FA key", fa_secret, fa_secret_len); /* check that MN-FA auth ext is valid before accepting the * key */ if (!auth_check(auth_aaa_key_alg_id_to_dynamics(ntohs( fa_key->alg_id)), fa_secret, fa_secret_len, (unsigned char *) ext->rep, ext->mf_auth)) { LOG2(LOG_ALERT, "MN-FA key from AAA does not match " "with MN-FA auth. ext.\n"); return 0; } } if (ext->mn_ha_key_material_aaa) { ha_key = (struct mn_ha_key_material_from_aaa *) (ext->mn_ha_key_material_aaa + 1); if (ext->mh_auth == NULL || !auth_is_protected(ext->mn_ha_key_material_aaa, ext->mh_auth)) { LOG2(LOG_ALERT, "MN-HA auth. ext. does not protect " "MN-HA key material from AAA\n"); return 0; } /* generate MN-HA key from key material */ ha_secret_len = MAXSHAREDSECRETLEN; if (auth_generate_key( config.mn_aaa_keygen_alg, config.mn_aaa_shared_secret, config.mn_aaa_shared_secret_len, (unsigned char *) (ha_key + 1), GET_GEN_MN_HA_KEY_REP_LEN( ext->mn_ha_key_material_aaa) - sizeof(struct mn_ha_key_material_from_aaa), nodeaddr, nodeaddrlen, ha_secret, &ha_secret_len)) { LOG2(LOG_ALERT, "MN-HA key generation with material " "from AAA failed\n"); return 0; } show_key_dump("MN-HA key", ha_secret, ha_secret_len); /* check that MN-HA auth ext is valid before accepting the * key */ if (!auth_check(auth_aaa_key_alg_id_to_dynamics( ntohs(ha_key->alg_id)), ha_secret, ha_secret_len, (unsigned char *) ext->rep, ext->mh_auth)) { LOG2(LOG_ALERT, "MN-HA key from AAA does not match " "with MN-HA auth. ext.\n"); return 0; } } /* Generated keys matched with authentication extensions - add new * dynamic security associations */ if (ext->mn_fa_key_material_aaa) { struct fa_spi_entry *spi; spi = malloc(sizeof(struct fa_spi_entry)); if (spi == NULL) { DEBUG(DEBUG_INFO, "Could not allocate memory for new " "FA security association\n"); return 0; } memset(spi, 0, sizeof(struct fa_spi_entry)); list_init_node(&spi->node); spi->spi = ntohl(fa_key->fa_spi); spi->addr.s_addr = addr.s_addr; spi->alg = auth_aaa_key_alg_id_to_dynamics(ntohs(fa_key->alg_id)); time(&spi->created); spi->lifetime = ntohl(fa_key->lifetime); memcpy(spi->shared_secret, fa_secret, sizeof(fa_secret)); spi->shared_secret_len = fa_secret_len; add_fa_spi(spi, 1); } if (ext->mn_ha_key_material_aaa) { config.spi = ntohl(ha_key->ha_spi); mn.use_auth_alg = config.auth_alg = auth_aaa_key_alg_id_to_dynamics(ntohs(ha_key->alg_id)); config.replay_meth = auth_aaa_key_replay_to_dynamics( ntohs(ha_key->replay_method)); memcpy(config.shared_secret, ha_secret, sizeof(ha_secret)); config.shared_secret_len = ha_secret_len; time(&config.mn_ha_key_timestamp); config.mn_ha_key_lifetime = ntohl(ext->mn_ha_key_material_aaa->lifetime); } mn.aaa_rekey = 0; return 1;}/* * Check if ext contains valid registration reply. * correct reply should have id[1] same as in request. * Return nonzero if it's valid, zero otherwise. */static int is_valid_reply(struct msg_extensions *ext, struct sockaddr_in addr){ int auth_alg; struct fa_spi_entry *fa_spi; ASSERT(ext != NULL); /* verify fields */ if (ext->rep == NULL || ext->rep->type != REG_REP) { LOG2(LOG_WARNING, "Received message from %s:%i was not a " "registration reply\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); return 0; }#ifndef MN_ENABLE_VALIDATION DEBUG(DEBUG_INFO, "MN - no message validation in use\n"); return 1;#else if ((ext->mn_fa_key_material_aaa != NULL || ext->mn_ha_key_material_aaa != NULL) && handle_reply_aaa(ext, addr.sin_addr) != 1) { LOG2(LOG_ALERT, "Registration reply validation failed for AAA " "related data - dropping reply\n"); return 0; } /* verify mac */ if (ext->mh_auth != NULL) { if (config.shared_secret_len < 0) { LOG2(LOG_ALERT, "MN-HA in reply, but security " "association does not exists yet\n"); return 0; } if (!auth_check(mn.use_auth_alg, config.shared_secret, config.shared_secret_len, (unsigned char *) ext->rep, ext->mh_auth)) { if (mn.use_auth_alg == AUTH_ALG_MD5) auth_alg = AUTH_ALG_MD5_RFC2002; else if (mn.use_auth_alg == AUTH_ALG_MD5_RFC2002) auth_alg = AUTH_ALG_MD5; else auth_alg = 0; if (auth_alg == 0 || !auth_check(auth_alg, config.shared_secret, config.shared_secret_len, (unsigned char *) ext->rep, ext->mh_auth)) { LOG2(LOG_ALERT, "Incorrect HA->MN authentication " "extension received in the reply\n"); if (config.use_aaa) mn.aaa_rekey = 1; return 0; } else { /* non-standard authentication method used */ DEBUG(DEBUG_MESSAGES, "Non-standard MAC calculation detected " "- trying to use the same method\n"); mn.use_auth_alg = auth_alg; return 0; } } } else if (ext->sk_auth != NULL && mn.session_key_len > 0) { if (!auth_check_vendor(config.auth_alg, mn.session_key, mn.session_key_len, (unsigned char *) ext->rep, ext->sk_auth)) { LOG2(LOG_ALERT, "Incorrect session key based " "authentication extension in the reply.\n"); return 0; } /* FAs cannot send session_keys */ if (ext->mn_keyrep != NULL) { DEBUG(DEBUG_MESSAGES, "Registration reply from FA " "contained mn_keyrep extension - dropped it\n"); /* Just clear the session key to prevent FAs from * sending them us. */ ext->mn_keyrep = NULL; } } else if (ext->rep->code < 64 || ext->rep->code > 127) { /* codes 64 .. 127 are for Foreign Agent denial; only require * authentication extension in messages that are from the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -