static void chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags, RADIUS_REQUEST_CTX reqctx) { int code, lrespkt; const char *secret, *reason = ""; chap *_this; u_char *respkt, *respkt0; int errorCode; RADIUS_REQUEST_CTX radctx; CHAP_ASSERT(context != NULL); reason = ""; errorCode = ERROR_AUTH_SERVER_TIMEOUT; _this = context; secret = radius_get_server_secret(_this->radctx); radctx = _this->radctx; _this->radctx = NULL; /* IMPORTANT */ respkt = respkt0 = ppp_packetbuf(_this->ppp, PPP_PROTO_CHAP) + HEADERLEN; lrespkt = _this->ppp->mru - HEADERLEN; if (pkt == NULL) { if (flags & RADIUS_REQUEST_TIMEOUT) reason = "timeout"; else if (flags & RADIUS_REQUEST_ERROR) reason = strerror(errno); else reason = "error"; goto auth_failed; } code = radius_get_code(pkt); if (code == RADIUS_CODE_ACCESS_REJECT) { reason="reject"; errorCode = ERROR_AUTHENTICATION_FAILURE; /* Windows peer will reset the password by this error code */ goto auth_failed; } else if (code != RADIUS_CODE_ACCESS_ACCEPT) { reason="error"; goto auth_failed; } if ((flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK) == 0 && (flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK) == 0) { reason="bad_authenticator"; goto auth_failed; } /* * Authetication OK */ switch (_this->type) { case PPP_AUTH_CHAP_MD5: chap_response(_this, 1, "OK", 2); break; case PPP_AUTH_CHAP_MS_V2: { struct RADIUS_MS_CHAP2_SUCCESS success; #ifdef USE_NPPPD_MPPE struct RADIUS_MPPE_KEY sendkey, recvkey; #endif size_t len; len = sizeof(success); if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT, RADIUS_VTYPE_MS_CHAP2_SUCCESS, &success, &len) != 0) { chap_log(_this, LOG_ERR, "no ms_chap2_success"); goto auth_failed; } #ifdef USE_NPPPD_MPPE if (_this->ppp->mppe.enabled != 0) { len = sizeof(sendkey); if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT, RADIUS_VTYPE_MPPE_SEND_KEY, &sendkey, &len) != 0) { chap_log(_this, LOG_ERR, "no mppe_send_key"); goto auth_failed; } len = sizeof(recvkey); if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT, RADIUS_VTYPE_MPPE_RECV_KEY, &recvkey, &len) != 0) { chap_log(_this, LOG_ERR, "no mppe_recv_key"); goto auth_failed; } mschap_radiuskey(_this->ppp->mppe.send.master_key, sendkey.salt, _this->authenticator, secret); mschap_radiuskey(_this->ppp->mppe.recv.master_key, recvkey.salt, _this->authenticator, secret); } #endif chap_response(_this, 1, success.str, sizeof(success.str)); break; } } ppp_process_radius_framed_ip(_this->ppp, pkt); return; auth_failed: chap_log(_this, LOG_WARNING, "Radius authentication request failed: %s", reason); /* No extra information */ chap_failure(_this, "FAILED", errorCode); }
static int radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop) { RADIUS_PACKET *radpkt; RADIUS_REQUEST_CTX radctx; radius_req_setting *rad_setting; char buf[128]; if (ppp->username[0] == '\0') return 0; radpkt = NULL; radctx = NULL; rad_setting = npppd_auth_radius_get_radius_acct_setting(ppp->realm); if (!radius_req_setting_has_server(rad_setting)) return 0; if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCOUNTING_REQUEST)) == NULL) goto fail; if (radius_prepare(rad_setting, (void *)(uintptr_t)ppp->id, &radctx, npppd_ppp_radius_acct_reqcb, 0) != 0) goto fail; /* NAS Information */ /* * RFC 2865 "5.4. NAS-IP-Address" or RFC 3162 "2.1. NAS-IPv6-Address" */ if (radius_prepare_nas_address(rad_setting, radpkt) != 0) goto fail; /* RFC 2865 "5.41. NAS-Port-Type" */ ATTR_INT32(RADIUS_TYPE_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_VIRTUAL); /* RFC 2865 "5.5. NAS-Port" */ ATTR_INT32(RADIUS_TYPE_NAS_PORT, ppp->id); /* npppd has no physical / virtual ports in design. */ /* RFC 2865 5.31. Calling-Station-Id */ if (ppp->calling_number[0] != '\0') ATTR_STR(RADIUS_TYPE_CALLING_STATION_ID, ppp->calling_number); /* Tunnel Protocol Information */ switch (ppp->tunnel_type) { case PPP_TUNNEL_L2TP: /* RFC 2868 3.1. Tunnel-Type */ ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_L2TP); if (l2tp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0) goto fail; break; case PPP_TUNNEL_PPTP: /* RFC 2868 3.1. Tunnel-Type */ ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_PPTP); if (pptp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0) goto fail; break; } /* Framed Protocol (PPP) Information */ /* RFC 2865 5.1 User-Name */ ATTR_STR(RADIUS_TYPE_USER_NAME, ppp->username); /* RFC 2865 "5.7. Service-Type" */ ATTR_INT32(RADIUS_TYPE_SERVICE_TYPE, RADIUS_SERVICE_TYPE_FRAMED); /* RFC 2865 "5.8. Framed-Protocol" */ ATTR_INT32(RADIUS_TYPE_FRAMED_PROTOCOL, RADIUS_FRAMED_PROTOCOL_PPP); /* RFC 2865 "5.8. Framed-IP-Address" */ if (ppp_ip_assigned(ppp) && !stop) ppp->realm_framed_ip_address = ppp->ppp_framed_ip_address; if (ppp->realm_framed_ip_address.s_addr != INADDR_ANY) { ATTR_INT32(RADIUS_TYPE_FRAMED_IP_ADDRESS, ntohl(ppp->realm_framed_ip_address.s_addr)); } /* Accounting */ /* RFC 2866 5.1. Acct-Status-Type */ ATTR_INT32(RADIUS_TYPE_ACCT_STATUS_TYPE, (stop) ? RADIUS_ACCT_STATUS_TYPE_STOP : RADIUS_ACCT_STATUS_TYPE_START); /* RFC 2866 5.2. Acct-Delay-Time */ ATTR_INT32(RADIUS_TYPE_ACCT_DELAY_TIME, 0); if (stop) { /* RFC 2866 5.3 Acct-Input-Octets */ ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_OCTETS, (uint32_t)(ppp->ibytes & 0xFFFFFFFFU)); /* LSB 32bit */ /* RFC 2866 5.4 Acct-Output-Octets */ ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_OCTETS, (uint32_t)(ppp->obytes & 0xFFFFFFFFU)); /* LSB 32bit */ } /* RFC 2866 5.5 Acct-Session-Id */ snprintf(buf, sizeof(buf), "%08X%08X", pppd->boot_id, ppp->id); ATTR_STR(RADIUS_TYPE_ACCT_SESSION_ID, buf); /* RFC 2866 5.6. Acct-Authentic */ ATTR_INT32(RADIUS_TYPE_ACCT_AUTHENTIC, RADIUS_ACCT_AUTHENTIC_RADIUS); if (stop) { /* RFC 2866 5.7. Acct-Session-Time */ ATTR_INT32(RADIUS_TYPE_ACCT_SESSION_TIME, ppp->end_monotime - ppp->start_monotime); /* RFC 2866 5.8 Acct-Input-Packets */ ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_PACKETS, ppp->ipackets); /* RFC 2866 5.9 Acct-Output-Packets */ ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_PACKETS, ppp->opackets); /* RFC 2866 5.10. Acct-Terminate-Cause */ if (ppp->terminate_cause != 0) ATTR_INT32(RADIUS_TYPE_ACCT_TERMINATE_CAUSE, ppp->terminate_cause); /* RFC 2869 5.1 Acct-Input-Gigawords */ ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, ppp->ibytes >> 32); /* RFC 2869 5.2 Acct-Output-Gigawords */ ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, ppp->obytes >> 32); } radius_set_request_authenticator(radpkt, radius_get_server_secret(radctx)); /* Send the request */ radius_request(radctx, radpkt); return 0; fail: ppp_log(ppp, LOG_WARNING, "radius accounting request failed: %m"); if (radctx != NULL) radius_cancel_request(radctx); if (radpkt != NULL) radius_delete_packet(radpkt); return -1; }
static void pap_radius_authenticate(pap *_this, const char *username, const char *password) { void *radctx; RADIUS_PACKET *radpkt; MD5_CTX md5ctx; int i, j, s_len, passlen; u_char ra[16], digest[16], pass[128]; const char *s; radius_req_setting *rad_setting = NULL; char buf0[MAX_USERNAME_LENGTH]; if ((rad_setting = npppd_get_radius_auth_setting(_this->ppp->pppd, _this->ppp)) == NULL) goto fail; if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST)) == NULL) goto fail; if (radius_prepare(rad_setting, _this, &radctx, pap_radius_response) != 0) { radius_delete_packet(radpkt); goto fail; } if (ppp_set_radius_attrs_for_authreq(_this->ppp, rad_setting, radpkt) != 0) goto fail; if (radius_put_string_attr(radpkt, RADIUS_TYPE_USER_NAME, npppd_ppp_get_username_for_auth(_this->ppp->pppd, _this->ppp, username, buf0)) != 0) goto fail; if (_this->radctx != NULL) radius_cancel_request(_this->radctx); _this->radctx = radctx; /* Create RADIUS User-Password Attribute (RFC 2865, 5.2.) */ s = radius_get_server_secret(_this->radctx); s_len = strlen(s); memset(pass, 0, sizeof(pass)); /* null padding */ passlen = MINIMUM(strlen(password), sizeof(pass)); memcpy(pass, password, passlen); if ((passlen % 16) != 0) passlen += 16 - (passlen % 16); radius_get_authenticator(radpkt, ra); MD5Init(&md5ctx); MD5Update(&md5ctx, s, s_len); MD5Update(&md5ctx, ra, 16); MD5Final(digest, &md5ctx); for (i = 0; i < 16; i++) pass[i] ^= digest[i]; while (i < passlen) { MD5Init(&md5ctx); MD5Update(&md5ctx, s, s_len); MD5Update(&md5ctx, &pass[i - 16], 16); MD5Final(digest, &md5ctx); for (j = 0; j < 16; j++, i++) pass[i] ^= digest[j]; } if (radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD, pass, passlen) != 0) goto fail; radius_request(_this->radctx, radpkt); return; fail: if (_this->radctx != NULL) radius_cancel_request(_this->radctx); pap_log(_this, LOG_ERR, "%s() failed: %m", __func__); pap_response(_this, 0, DEFAULT_ERROR_MESSAGE); return; }