/** callback function which works for each PPP session */ static int npppd_iface_network_input_delegate(struct radish *radish, void *args0) { npppd_ppp *ppp; struct sockaddr_npppd *snp; struct npppd_iface_network_input_arg *args; snp = radish->rd_rtent; if (snp->snp_type == SNP_PPP) { args = args0; ppp = snp->snp_data_ptr; if (ppp_iface(ppp) != args->_this) return 0; #ifdef USE_NPPPD_MPPE if (MPPE_SEND_READY(ppp)) { /* output via MPPE if MPPE started */ mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, args->pktp, args->lpktp); } else if (MPPE_IS_REQUIRED(ppp)) { /* in case MPPE not started but MPPE is mandatory, */ /* it is not necessary to log because of multicast. */ return 0; } #endif ppp_output(ppp, PPP_PROTO_IP, 0, 0, args->pktp, args->lpktp); } return 0; }
static void npppd_iface_network_input_ipv4(npppd_iface *_this, u_char *pktp, int lpktp) { struct ip *iphdr; npppd *_npppd; npppd_ppp *ppp; struct npppd_iface_network_input_arg input_arg; NPPPD_IFACE_ASSERT(_this != NULL); NPPPD_IFACE_ASSERT(pktp != NULL); iphdr = (struct ip *)pktp; _npppd = _this->npppd; if (lpktp < sizeof(iphdr)) { npppd_iface_log(_this, LOG_ERR, "Received short packet."); return; } if (IN_MULTICAST(ntohl(iphdr->ip_dst.s_addr))) { NPPPD_IFACE_ASSERT(((npppd *)(_this->npppd))->rd != NULL); input_arg._this = _this; input_arg.pktp = pktp; input_arg.lpktp = lpktp; /* delegate */ rd_walktree(((npppd *)(_this->npppd))->rd, npppd_iface_network_input_delegate, &input_arg); return; } ppp = npppd_get_ppp_by_ip(_npppd, iphdr->ip_dst); if (ppp == NULL) { #ifdef NPPPD_DEBUG log_printf(LOG_INFO, "%s received a packet to unknown " "%s.", _this->ifname, inet_ntoa(iphdr->ip_dst)); #endif return; } #ifndef NO_ADJUST_MSS if (ppp->adjust_mss) { adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru)); } #endif if (ppp->timeout_sec > 0 && !ip_is_idle_packet(iphdr, lpktp)) ppp_reset_idle_timeout(ppp); #ifdef USE_NPPPD_MPPE if (MPPE_SEND_READY(ppp)) { /* output via MPPE if MPPE started */ mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, pktp, lpktp); return; } else if (MPPE_IS_REQUIRED(ppp)) { /* in case MPPE not started but MPPE is mandatory */ ppp_log(ppp, LOG_WARNING, "A packet received from network, " "but MPPE is not started."); return; } #endif ppp_output(ppp, PPP_PROTO_IP, 0, 0, pktp, lpktp); }
/*********************************************************************** * Proxy Authentication ***********************************************************************/ int chap_proxy_authen_prepare(chap *_this, dialin_proxy_info *dpi) { CHAP_ASSERT(dpi->auth_type == PPP_AUTH_CHAP_MD5); CHAP_ASSERT(_this->state == CHAP_STATE_INITIAL); _this->pktid = dpi->auth_id; #ifdef USE_NPPPD_MPPE if (MPPE_IS_REQUIRED(_this->ppp) && _this->type != PPP_AUTH_CHAP_MS_V2) { chap_log(_this, LOG_ALERT, "mppe is required but try to start chap " "type=0x%02x", dpi->auth_type); return -1; } #endif /* authentication */ if (strlen(dpi->username) >= sizeof(_this->name)) { chap_log(_this, LOG_NOTICE, "\"Proxy Authen Name\" is too long."); return -1; } if (dpi->lauth_chall >= sizeof(_this->chall)) { chap_log(_this, LOG_NOTICE, "\"Proxy Authen Challenge\" is too long."); return -1; } /* copy the authenticaiton properties */ CHAP_ASSERT(_this->ppp->proxy_authen_resp == NULL); if ((_this->ppp->proxy_authen_resp = malloc(dpi->lauth_resp)) == NULL) { chap_log(_this, LOG_ERR, "malloc() failed in %s(): %m", __func__); return -1; } memcpy(_this->ppp->proxy_authen_resp, dpi->auth_resp, dpi->lauth_resp); _this->ppp->lproxy_authen_resp = dpi->lauth_resp; _this->challid = dpi->auth_id; strlcpy(_this->name, dpi->username, sizeof(_this->name)); memcpy(_this->chall, dpi->auth_chall, dpi->lauth_chall); _this->lchall = dpi->lauth_chall; _this->state = CHAP_STATE_PROXY_AUTHENTICATION; return 0; }
/** Start CHAP as a authenticator. Send a challenge */ void chap_start(chap *_this) { u_char *challp, *challp0; int lmyname; CHAP_ASSERT(_this != NULL); CHAP_ASSERT(_this->ppp != NULL); if (_this->state == CHAP_STATE_PROXY_AUTHENTICATION) { _this->type = PPP_AUTH_CHAP_MD5; _this->state = CHAP_STATE_AUTHENTICATING; chap_authenticate(_this, _this->ppp->proxy_authen_resp, _this->ppp->lproxy_authen_resp); return; } if (_this->state == CHAP_STATE_INITIAL || _this->state == CHAP_STATE_SENT_CHALLENGE) { if (_this->ntry > 0) { _this->ntry--; _this->type = _this->ppp->peer_auth; /* The type is supported? */ if (_this->type != PPP_AUTH_CHAP_MS_V2 && _this->type != PPP_AUTH_CHAP_MD5) { chap_log(_this, LOG_ALERT, "Requested authentication type(0x%x) " "is not supported.", _this->type); ppp_set_disconnect_cause(_this->ppp, PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE, PPP_PROTO_CHAP, 2 /* local */, NULL); ppp_stop(_this->ppp, "Authentication Required"); return; } #ifdef USE_NPPPD_MPPE /* The peer must use MS-CHAP-V2 as the type */ if (MPPE_IS_REQUIRED(_this->ppp) && _this->type != PPP_AUTH_CHAP_MS_V2) { chap_log(_this, LOG_ALERT, "mppe is required but try to start chap " "type=0x%02x", _this->type); ppp_set_disconnect_cause(_this->ppp, PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE, PPP_PROTO_CHAP, 2 /* local */, NULL); ppp_stop(_this->ppp, "Authentication Required"); return; } #endif /* Generate a challenge packet and send it */ challp = ppp_packetbuf(_this->ppp, PPP_AUTH_CHAP); challp += HEADERLEN; challp0 = challp; chap_create_challenge(_this); PUTCHAR(_this->lchall, challp); memcpy(challp, &_this->chall, _this->lchall); challp += _this->lchall; lmyname = strlen(_this->myname); memcpy(challp, _this->myname, lmyname); challp += lmyname; _this->challid = ++_this->pktid; ppp_output(_this->ppp, PPP_PROTO_CHAP, CHAP_CHALLENGE, _this->challid, challp0, challp - challp0); _this->state = CHAP_STATE_SENT_CHALLENGE; TIMEOUT((void (*)(void *))chap_start, _this, CHAP_TIMEOUT); } else { chap_log(_this, LOG_INFO, "Client did't respond our challenage."); ppp_set_disconnect_cause(_this->ppp, PPP_DISCON_AUTH_FSM_TIMEOUT, PPP_PROTO_CHAP, 0, NULL); ppp_stop(_this->ppp, "Authentication Required"); } } }