📄 rlm_eap_ikev2.c
字号:
/* * rlm_eap_ikev2.c - Handles that are called from eap * * This file is part of rlm_eap_ikev2 freeRADIUS module which implements * EAP-IKEv2 protocol functionality. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright (C) 2005-2006 Krzysztof Rzecki <krzysztof.rzecki@ccns.pl> * Copyright (C) 2005-2006 Rafal Mijal <rafal.mijal@ccns.pl> * Copyright (C) 2005-2006 Piotr Marnik <piotr.marnik@ccns.pl> * Copyright (C) 2005-2006 Pawel Matejski <pawel.matejski@ccns.pl> * Copyright 1999-2007 The FreeRADIUS server project * */#include <freeradius-devel/radiusd.h>#include "eap.h"#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <freeradius-devel/rad_assert.h>#include "logging_impl.h"#include <EAPIKEv2/connector.h>#include "ike_conf.h"#define PW_IKEV2_CHALLENGE 1#define PW_IKEV2_RESPONSE 2#define PW_IKEV2_SUCCESS 3#define PW_IKEV2_FAILURE 4#define PW_IKEV2_MAX_CODES 4#define IKEV2_HEADER_LEN 4#define IKEV2_MPPE_KEY_LEN 32/* * Add value pair to reply: copied from FreeRADIUS */static void add_reply(VALUE_PAIR** vp, const char* name, const char* value, int len){ VALUE_PAIR *reply_attr; reply_attr = pairmake(name, "", T_OP_EQ); if (!reply_attr) { radlog(L_INFO, IKEv2_LOG_PREFIX "add_reply failed to create attribute %s: %s", name, fr_strerror()); return; } memcpy(reply_attr->vp_octets, value, len); reply_attr->length = len; pairadd(vp, reply_attr);}static int set_mppe_keys(EAP_HANDLER *handler){ unsigned char *p; struct IKEv2Session *session; VALUE_PAIR **outvps; session = ((struct IKEv2Data*)handler->opaque)->session; if (session->eapKeyData==NULL){ radlog( L_INFO,IKEv2_LOG_PREFIX "Key session not available!!!"); return 1; } /* outvps is the session to the client. */ outvps= &handler->request->reply->vps; p = session->eapKeyData; add_reply(outvps, "MS-MPPE-Recv-Key",(const char*) p, IKEV2_MPPE_KEY_LEN); p += IKEV2_MPPE_KEY_LEN; add_reply(outvps, "MS-MPPE-Send-Key",(const char*) p, IKEV2_MPPE_KEY_LEN); return 0;}// Compose Radius like message from table of output bytesstatic int ComposeRadMsg(uint8_t *out,u_int32_t olen, EAP_DS *eap_ds){ eap_ds->request->type.type = PW_EAP_IKEV2; eap_ds->request->code = ((struct EAPHeader *)out)->Code; if(eap_ds->request->code<=PW_EAP_REQUEST && olen>4) { int lenn=(int)ntohs(((struct EAPHeader *)out)->Length); eap_ds->request->type.data = malloc(lenn); if (eap_ds->request->type.data == NULL) { radlog(L_ERR, IKEv2_LOG_PREFIX "out of memory"); return 1; } memcpy(eap_ds->request->type.data,out+5,lenn-5); eap_ds->request->type.length = lenn-5; } else { eap_ds->request->type.data=NULL; eap_ds->request->type.length=0; } return 0;}/** * Free memory after EAP-IKEv2 module usage */static int ikev2_detach(void *type_data){ radlog(L_DBG,IKEv2_LOG_PREFIX "dettach"); struct ikev2_ctx *data=(struct ikev2_ctx*)type_data; if(data) { Free_ikev2_ctx(data); data=NULL; } return 0;}/** * Free memory after finished IKEv2 session */static void ikev2_free_opaque(void *opaque){ radlog(L_DBG,IKEv2_LOG_PREFIX "Free session data"); struct IKEv2Data *ikev2_data=(struct IKEv2Data*)opaque; if(ikev2_data->session) { if(ikev2_data->session->Status!=IKEv2_SST_ESTABLISHED) { radlog(L_DBG, IKEv2_LOG_PREFIX "Unfinished IKEv2 session - cleanup!!!"); IKEv2EndSession(ikev2_data->i2,ikev2_data->session); ikev2_data->session=NULL; } else { radlog(L_DBG, IKEv2_LOG_PREFIX "Unfinished IKEv2 session - keep it!!!"); ikev2_data->session=NULL; } } int fastDeleted=FreeSessionIfExpired(ikev2_data->i2,time(NULL)); if(fastDeleted) { radlog(L_DBG,IKEv2_LOG_PREFIX "Deleted %d expired IKEv2 sessions",fastDeleted); } free(ikev2_data);}/** * Configure EAP-ikev2 handler */static int ikev2_attach(CONF_SECTION *conf, void **type_data){ radlog(L_DBG,IKEv2_LOG_PREFIX "attach"); char *default_authtype=NULL; char *usersfilename=NULL; char *server_authtype=NULL; char *server_idtype=NULL; CONF_PARSER module_config[] = { { "CA_file", PW_TYPE_STRING_PTR, offsetof(ikev2_ctx,trusted),NULL,NULL }, { "private_key_file",PW_TYPE_STRING_PTR, offsetof(ikev2_ctx,pkfile),NULL,NULL }, { "private_key_password",PW_TYPE_STRING_PTR, offsetof(ikev2_ctx,pkfile_pwd),NULL,NULL }, { "certificate_file", PW_TYPE_STRING_PTR, offsetof(ikev2_ctx,certfile),NULL,NULL }, { "crl_file", PW_TYPE_STRING_PTR, offsetof(ikev2_ctx,crl_file),NULL,NULL }, { "id", PW_TYPE_STRING_PTR, offsetof(ikev2_ctx,id),NULL,NULL }, { "fragment_size",PW_TYPE_INTEGER, offsetof(ikev2_ctx,max_fragment_size),NULL,IKEv2_DEFAULT_MAX_FRAGMENT_SIZE_STR}, { "DH_counter_max", PW_TYPE_INTEGER, offsetof(ikev2_ctx,DHCounterMax),NULL,IKEv2_DEFAULT_DH_COUNTER_MAX_STR}, { "default_authtype",PW_TYPE_STRING_PTR, 0,&default_authtype,"both" }, { "usersfile",PW_TYPE_STRING_PTR, 0,&usersfilename,"${confdir}/users" }, { "server_authtype",PW_TYPE_STRING_PTR, 0,&server_authtype,"secret" }, { "idtype",PW_TYPE_STRING_PTR, 0,&server_idtype,IKEv2_DEFAULT_IDTYPE_STR}, { "certreq",PW_TYPE_BOOLEAN, offsetof(ikev2_ctx,sendCertReq),NULL,"no"}, { "fast_DH_exchange",PW_TYPE_BOOLEAN, offsetof(ikev2_ctx,enableFastDHEx),NULL,"no"}, { "fast_timer_expire",PW_TYPE_INTEGER, offsetof(ikev2_ctx,fastExpire),NULL,"900"}, { "enable_fast_reauth",PW_TYPE_BOOLEAN, offsetof(ikev2_ctx,enableFastReconnect),NULL,"yes"}, { NULL, -1, 0, NULL, NULL } /* end the list */ }; ikev2_set_log_callback(vxlogf); struct ikev2_ctx *i2; i2 = Create_ikev2_ctx(); if (i2 == NULL) { radlog(L_ERR,IKEv2_LOG_PREFIX "Error: Can't allocate mem for i2."); return -1; } *type_data=i2; if (cf_section_parse(conf,i2, module_config) < 0) { ikev2_detach(i2); return -1; } hexalize(&i2->id,&i2->idlen); //hexalize(&i2->pwd,&i2->pwdlen); i2->authtype=rad_get_authtype(server_authtype); if(!i2->id) { ikev2_detach(i2); radlog(L_ERR,IKEv2_LOG_PREFIX "'id' configuration option is required!!!"); return -1; } switch(i2->authtype) { case IKEv2_AUTH_SK: break; case IKEv2_AUTH_CERT: if(!i2->certfile || !i2->pkfile) { ikev2_detach(i2); radlog(L_ERR,IKEv2_LOG_PREFIX "'certificate_file' and 'private_key_file' items are required for 'cert' auth type"); return -1; } if(!file_exists(i2->certfile)) { radlog(L_ERR,IKEv2_LOG_PREFIX "Can not open 'certificate_file' %s",i2->certfile); ikev2_detach(i2); return -1; } if(!file_exists(i2->pkfile)) { radlog(L_ERR,IKEv2_LOG_PREFIX "Can not open 'private_key_file' %s",i2->pkfile); ikev2_detach(i2); return -1; } break; } if(!i2->trusted) { radlog(L_AUTH,IKEv2_LOG_PREFIX "'CA_file' item not set, client cert based authentication will fail"); } else { if(!file_exists(i2->trusted)) { radlog(L_ERR,IKEv2_LOG_PREFIX "Can not open 'CA_file' %s",i2->trusted); ikev2_detach(i2); return -1; } } if(i2->crl_file) { if(!file_exists(i2->crl_file)) { radlog(L_ERR,IKEv2_LOG_PREFIX "Can not open 'crl_file' %s",i2->crl_file); ikev2_detach(i2); return -1; } radlog(L_DBG,IKEv2_LOG_PREFIX "Using CRL file: %s",i2->crl_file); } i2->idtype=IdTypeFromName(server_idtype); if(i2->idtype<=0) { radlog(L_ERR,IKEv2_LOG_PREFIX "Unsupported 'idtype': %s",server_idtype); free(server_idtype); server_idtype=NULL; ikev2_detach(i2); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -