⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rlm_jradius.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * rlm_jradius - The FreeRADIUS JRadius Server Module * Copyright (C) 2004-2006 PicoPoint, B.V. * Copyright (c) 2007 David Bird *  * 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 * *  This module is used to connect FreeRADIUS to the JRadius server.  *  JRadius is a Java RADIUS client and server framework, see doc/rlm_jradius *  and http://jradius.net/ for more information.  * *  Author(s): David Bird <dbird@acm.org> * *  Connection pooling code based on rlm_sql, see rlm_sql/sql.c for copyright and license. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/signal.h>#include <sys/types.h>#include <fcntl.h>#include <poll.h>#include <freeradius-devel/ident.h>RCSID("$Id: rlm_jradius.c,v 1.3 2007/11/23 13:46:57 aland Exp $")#include <freeradius-devel/autoconf.h>#include <freeradius-devel/libradius.h>#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/conffile.h>#ifdef HAVE_PTHREAD_H#include <pthread.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifndef O_NONBLOCK#define O_NONBLOCK O_NDELAY#endifstatic const int JRADIUS_PORT         = 1814;static const int HALF_MESSAGE_LEN     = 16384;static const int MESSAGE_LEN          = 32768;static const int JRADIUS_authenticate = 1;static const int JRADIUS_authorize    = 2;static const int JRADIUS_preacct      = 3;static const int JRADIUS_accounting   = 4;static const int JRADIUS_checksimul   = 5;static const int JRADIUS_pre_proxy    = 6;static const int JRADIUS_post_proxy   = 7;static const int JRADIUS_post_auth    = 8;#define LOG_PREFIX  "rlm_jradius: "#define MAX_HOSTS   4typedef struct jradius_socket {  int  id;#ifdef HAVE_PTHREAD_H  pthread_mutex_t mutex;#endif  struct jradius_socket *next;  enum { is_connected, not_connected } state;    union {    int sock;  } con;} JRSOCK;typedef struct jradius_inst {  time_t      connect_after;  JRSOCK    * sock_pool;  JRSOCK    * last_used;  char     * name;  char     * host   [MAX_HOSTS];  uint32_t   ipaddr [MAX_HOSTS];  int        port   [MAX_HOSTS];  int        timeout;  int        allow_codechange;  int        allow_idchange;  int        onfail;  char     * onfail_s;  int        keepalive;  int        jrsock_cnt;} JRADIUS;typedef struct _byte_array{  unsigned int size;  unsigned int pos;  unsigned int left;  unsigned char * b;} byte_array;static CONF_PARSER module_config[] = {  { "name",         PW_TYPE_STRING_PTR,  offsetof(JRADIUS, name),       NULL,  "localhost"},  { "primary",      PW_TYPE_STRING_PTR,  offsetof(JRADIUS, host[0]),    NULL,  "localhost"},  { "secondary",    PW_TYPE_STRING_PTR,  offsetof(JRADIUS, host[1]),    NULL,  NULL},  { "tertiary",     PW_TYPE_STRING_PTR,  offsetof(JRADIUS, host[2]),    NULL,  NULL},  { "timeout",      PW_TYPE_INTEGER,     offsetof(JRADIUS, timeout),    NULL,  "5"},  { "onfail",       PW_TYPE_STRING_PTR,  offsetof(JRADIUS, onfail_s),   NULL,  NULL},  { "keepalive",    PW_TYPE_BOOLEAN,     offsetof(JRADIUS, keepalive),  NULL,  "yes"},  { "connections",  PW_TYPE_INTEGER,     offsetof(JRADIUS, jrsock_cnt), NULL,  "8"},  { "allow_codechange", PW_TYPE_BOOLEAN, offsetof(JRADIUS, allow_codechange),  NULL,  "no"},  { "allow_idchange",   PW_TYPE_BOOLEAN, offsetof(JRADIUS, allow_idchange),    NULL,  "no"},  { NULL, -1, 0, NULL, NULL }};static int connect_socket(JRSOCK *jrsock, JRADIUS *inst){  struct sockaddr_in local_addr, serv_addr;  int i, connected = 0;  char buff[128];  int sock;  /*   *     Connect to jradius servers until we succeed or die trying   */  for (i = 0; !connected && i < MAX_HOSTS && inst->ipaddr[i] > 0; i++) {    /*     *     Allocate a TCP socket     */    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {      radlog(L_ERR, LOG_PREFIX "could not allocate TCP socket");      goto failed;    }        /*     *     If we have a timeout value set, make the socket non-blocking     */    if (inst->timeout > 0 &&	fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK) == -1) {      radlog(L_ERR, LOG_PREFIX "could not set non-blocking on socket");      goto failed;    }        /*     *     Bind to any local port     */    memset(&local_addr, 0, sizeof(local_addr));    local_addr.sin_family = AF_INET;    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);    local_addr.sin_port = htons(0);        if (bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) {      radlog(L_ERR, LOG_PREFIX "could not locally bind TCP socket");      goto failed;    }        /*     *     Attempt connection to remote server     */    memset(&serv_addr, 0, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    memcpy((char *) &serv_addr.sin_addr, &(inst->ipaddr[i]), 4);    serv_addr.sin_port = htons(inst->port[i]);        if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {      if (inst->timeout > 0 && (errno == EINPROGRESS || errno == EWOULDBLOCK)) {	/*	 *     Wait to see if non-blocking socket connects or times-out	 */	struct pollfd pfd;	memset(&pfd, 0, sizeof(pfd));	pfd.fd = sock;	pfd.events = POLLOUT;	if (poll(&pfd, 1, inst->timeout * 1000) == 1 && pfd.revents) {	  /*	   *     Lets make absolutely sure we are connected	   */	  struct sockaddr_in sa;	  unsigned int salen = sizeof(sa);	  if (getpeername(sock, (struct sockaddr *) &sa, &salen) != -1) {	    /*	     *     CONNECTED! break out of for-loop	     */	    connected = 1;	    break;	  }	}      }      /*       *     Timed-out       */      radlog(L_ERR, LOG_PREFIX "could not connect to %s:%d", 	     ip_ntoa(buff, inst->ipaddr[i]), inst->port[i]);    } else {      /*       *     CONNECTED (instantly)! break out of for-loop       */      connected = 1;      break;    }    /*     *     Unable to connect, cleanup and start over     */    close(sock); sock=0;  }  if (!connected) {    radlog(L_ERR, LOG_PREFIX "could not find any jradius server!");    goto failed;  }  /*   *     If we previously set the socket to non-blocking, restore blocking    */  if (inst->timeout > 0 &&      fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK) == -1) {    radlog(L_ERR, LOG_PREFIX "could not set blocking on socket");    goto failed;  }  jrsock->state = is_connected;  jrsock->con.sock = sock;  return 1; failed:  if (sock > 0) { shutdown(sock, 2); close(sock); }  jrsock->state = not_connected;  return 0;}static void close_socket(UNUSED JRADIUS * inst, JRSOCK *jrsock){  radlog(L_INFO, "rlm_jradius: Closing JRadius connection %d", jrsock->id);  if (jrsock->con.sock > 0) {     shutdown(jrsock->con.sock, 2);     close(jrsock->con.sock);   }  jrsock->state = not_connected;  jrsock->con.sock = 0;}static void free_socket(JRADIUS * inst, JRSOCK *jrsock) {  close_socket(inst, jrsock);  if (inst->keepalive) {#ifdef HAVE_PTHREAD_H    pthread_mutex_destroy(&jrsock->mutex);#endif    free(jrsock);  }}static int socket_send(JRSOCK *jrsock, unsigned char *b, unsigned int blen) {  return send(jrsock->con.sock, b, blen, 0);}static int init_socketpool(JRADIUS * inst){  int i, rcode;  int success = 0;  JRSOCK *jrsock;    inst->connect_after = 0;  inst->sock_pool = NULL;    for (i = 0; i < inst->jrsock_cnt; i++) {    radlog(L_INFO, "rlm_jradius: starting JRadius connection %d", i);        if ((jrsock = rad_malloc(sizeof(*jrsock))) == 0) return -1;        memset(jrsock, 0, sizeof(*jrsock));    jrsock->id = i;    jrsock->state = not_connected;#ifdef HAVE_PTHREAD_H    rcode = pthread_mutex_init(&jrsock->mutex,NULL);    if (rcode != 0) {      radlog(L_ERR, "rlm_jradius: Failed to init lock: %s", strerror(errno));      return 0;    }#endif    if (time(NULL) > inst->connect_after)      if (connect_socket(jrsock, inst))	success = 1;        jrsock->next = inst->sock_pool;    inst->sock_pool = jrsock;  }  inst->last_used = NULL;    if (!success) {    radlog(L_DBG, "rlm_jradius: Failed to connect to JRadius server.");  }    return 1;}static void free_socketpool(JRADIUS * inst){  JRSOCK *cur;  JRSOCK *next;  for (cur = inst->sock_pool; cur; cur = next) {    next = cur->next;    free_socket(inst, cur);  }    inst->sock_pool = NULL;}static JRSOCK * get_socket(JRADIUS * inst){  JRSOCK *cur, *start;  int tried_to_connect = 0;  int unconnected = 0;  start = inst->last_used;  if (!start) start = inst->sock_pool;    cur = start;    while (cur) {#ifdef HAVE_PTHREAD_H    if (pthread_mutex_trylock(&cur->mutex) != 0) {      goto next;    } #endif        if ((cur->state == not_connected) && (time(NULL) > inst->connect_after)) {      radlog(L_INFO, "rlm_jradius: Trying to (re)connect unconnected handle %d", cur->id);      tried_to_connect++;      connect_socket(cur, inst);    }        if (cur->state == not_connected) {      radlog(L_DBG, "rlm_jradius: Ignoring unconnected handle %d", cur->id);      unconnected++;#ifdef HAVE_PTHREAD_H      pthread_mutex_unlock(&cur->mutex);#endif      goto next;    }        radlog(L_DBG, "rlm_jradius: Reserving JRadius socket id: %d", cur->id);        if (unconnected != 0 || tried_to_connect != 0) {      radlog(L_INFO, "rlm_jradius: got socket %d after skipping %d unconnected handles, tried to reconnect %d though", 	     cur->id, unconnected, tried_to_connect);    }    inst->last_used = cur->next;    return cur;      next:    cur = cur->next;    if (!cur) cur = inst->sock_pool;    if (cur == start) break;  }    radlog(L_INFO, "rlm_jradius: There are no sockets to use! skipped %d, tried to connect %d", 	 unconnected, tried_to_connect);  return NULL;}static int release_socket(UNUSED JRADIUS * inst, JRSOCK * jrsock){#ifdef HAVE_PTHREAD_H  pthread_mutex_unlock(&jrsock->mutex);#endif    radlog(L_DBG, "rlm_jradius: Released JRadius socket id: %d", jrsock->id);    return 0;}/* *     Initialize the jradius module */static int jradius_instantiate(CONF_SECTION *conf, void **instance){  JRADIUS *inst = (JRADIUS *) instance;  char host[128], b[128], *h;  int i, p, idx, port;  inst = rad_malloc(sizeof(JRADIUS));  memset(inst, 0, sizeof(JRADIUS));  if (cf_section_parse(conf, inst, module_config) < 0) {    free(inst);    return -1;  }  for (i = 0, idx = 0; i < MAX_HOSTS; i++) {    if (inst->host[i] && strlen(inst->host[i]) < sizeof(host)) {      h = inst->host[i];      p = JRADIUS_PORT;            strcpy(b, h);      if (sscanf(b, "%[^:]:%d", host, &port) == 2) { h = host; p = port; }      if (h) {	fr_ipaddr_t ipaddr;	if (ip_hton(h, AF_INET, &ipaddr) < 0) {	  radlog(L_ERR, "Can't find IP address for host %s", h);	  continue;	}	if ((inst->ipaddr[idx] = ipaddr.ipaddr.ip4addr.s_addr) != htonl(INADDR_NONE)) {	  inst->port[idx] = p;	  radlog(L_INFO, LOG_PREFIX "configuring jradius server %s:%d", h, p);	  idx++;	} else {	  radlog(L_ERR, LOG_PREFIX "invalid jradius server %s", h);	}      }    }  }  if (inst->keepalive) init_socketpool(inst);  inst->onfail = RLM_MODULE_FAIL;  if (inst->onfail_s) {    if      (!strcmp(inst->onfail_s, "NOOP"))    inst->onfail = RLM_MODULE_NOOP;    else if (!strcmp(inst->onfail_s, "REJECT"))  inst->onfail = RLM_MODULE_REJECT;    else if (!strcmp(inst->onfail_s, "OK"))      inst->onfail = RLM_MODULE_OK;    else if (!strcmp(inst->onfail_s, "FAIL"))    inst->onfail = RLM_MODULE_FAIL;    else radlog(L_ERR, LOG_PREFIX "invalid jradius 'onfail' state %s", inst->onfail_s);  }  *instance = inst;  return 0;}/* *     Initialize a byte array buffer structure */static void init_byte_array(byte_array * ba, unsigned char *b, int blen){  ba->b = b;  ba->size = ba->left = blen;  ba->pos = 0;}/* *     Pack a single byte into a byte array buffer */static int pack_byte(byte_array * ba, unsigned char c){  if (ba->left < 1) return -1;  ba->b[ba->pos] = c;  ba->pos++;  ba->left--;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -