📄 radiusd.c
字号:
/* * Copyright (C) 1999-2004 Francesco P. Lovergine. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms stated in the LICENSE file which should be * enclosed with sources. */static char rcsid[] = "$Id: radiusd.c,v 1.9.4.3 2004/08/27 21:45:16 flovergine Exp $";#define __MAIN__#include "yard.h"#include "global.h"static AUTH_REQ *first_request;/* * */int main( int argc,char **argv ){ UINT4 then; char argval; char argnum; int i; int t; int pid; fd_set readfds; int status; progname = *argv++; argc--; sockaddr = 0; debug_flag = 0; debug_mem = 0; spawn_flag = 0; radius_gdbm = 0; accept_zero = 0; do_clean = 0; max_requests = MAX_REQUESTS; max_request_time = MAX_REQUEST_TIME; max_proxy_time = MAX_PROXY_TIME; radacct_dir = RADACCT_DIR; radius_dir = RADIUS_DIR; alt_passwd = (char *)NULL; signal(SIGHUP, sig_hup); signal(SIGINT, sig_fatal); /* disable handler when debugging */ signal(SIGQUIT, sig_fatal); signal(SIGILL, sig_fatal); signal(SIGTRAP, sig_fatal);#if defined(SIGABRT) /* SIGABRT is POSIX.1 */ signal(SIGABRT, sig_fatal);#else signal(SIGIOT, sig_fatal); /* SIGIOT is obsolete */#endif signal(SIGFPE, sig_fatal); signal(SIGTERM, sig_fatal); signal(SIGCHLD, sig_cleanup);#if defined(SIGWINCH) signal(SIGWINCH, sig_hup);#endif signal(SIGUSR1, sig_usr1); signal(SIGUSR2, sig_usr2); for (i=0; i< RR_MAX; i++) { report[i] = 0; } while(argc) { if(**argv != '-') usage(); argval = *(*argv + 1); argnum = *(*argv + 2); argc--; argv++; switch(argval) { case 'a': if(argc == 0) usage(); radacct_dir = *argv; argc--; argv++; break; case 'b': /* use gdbm users file */ radius_gdbm = 1; break; case 'c': do_clean++; break; case 'd': if(argc == 0) usage(); radius_dir = *argv; argc--; argv++; break; case 'f': if(argc == 0) usage(); alt_passwd = *argv; argc--; argv++; break; case 'h': usage(); break; case 'i': if(argc == 0) usage(); sockaddr = get_ipaddr(*argv); argc--; argv++; break; case 'l': /* change logging from syslog */ if(argc == 0) usage(); radius_log = *argv; argc--; argv++; break; case 'm': /* debug memory */ if (isdigit(argnum)) debug_mem = argnum - '0'; else debug_mem++; break; case 'p': /* set radius port */ if(argc == 0) usage(); radius_port = (u_short)atoi(*argv); argc--; argv++; break; case 'o': /* accept all-zero accounting request authenticators */ accept_zero = 1; break; case 'q': /* set max queue size */ if(argc == 0) usage(); max_requests = (int)atoi(*argv); argc--; argv++; break; case 's': /* spawing processes mode */ spawn_flag = 1; break; case 't': /* set max time out in seconds */ if(argc == 0) usage(); max_request_time = (int)atoi(*argv); argc--; argv++; break; case 'v': version(); break; case 'w': /* set proxy time in seconds */ if(argc == 0) usage(); max_proxy_time = (int)atoi(*argv); argc--; argv++; break; case 'x': if (isdigit(argnum)) debug_flag = argnum - '0'; else debug_flag++; break; case 'z': /* debugging: -b -s -x -d . -a ra */ radius_gdbm = 1; spawn_flag = 0; debug_flag++; radius_dir = "."; radacct_dir = "ra"; break;#if defined(PAM) case 'P': usepamauth=1; break; case 'A': usepamacct=1; break;#endif default: usage(); break; } } if (debug_flag) { if (radius_log == NULL) { /* * for backward compatibility * send messages to users tty */ radius_log = "/dev/tty"; } else if (strcmp(radius_log, "syslog") == 0) { /* * allow user to override backward compatibility * and send debug to syslog */ radius_log = (char *)NULL; } } debug("initializing dictionary\n"); /* Initialize the dictionary */ if(dict_init() != 0) { rad_exit(-1); } dict_dump(); debug("initializing configuration values\n"); /* Initialize Configuration Values */ if(config_init() != 0) { rad_exit(-1); } /* * Disconnect from session */ debug("Disconnecting from session\n"); if(debug_flag == 0) { pid = fork(); if(pid < 0) { log_err("system error: could not fork at startup\n"); rad_exit(-1); } if(pid > 0) { exit(0); } } /* * Disconnect from tty */ debug("Disconnecting from tty\n"); for (t = 32; t >= 3; t--) { close(t); } /* Show our stuff */ log_version(); if (debug_flag) { log_err("debug mode %d\n",debug_flag); } if (debug_mem) { log_err("memory debug mode %d\n",debug_mem); } /* Open RADIUS socket */ sockfd = open_udpsock(&radius_port,PW_AUTH_UDP_PORT,"radius"); /* Open Accounting socket */ radacct_port = radius_port + 1; acctfd = open_udpsock(&radacct_port,PW_ACCT_UDP_PORT,"radacct"); /* * Open Proxy Socket. * We send to proxy servers from this socket, so replies return to it */ radproxy_port = radius_port + 5; radpracct_port = radius_port + 6; proxyfd = open_udpsock(&radproxy_port,PW_PROXY_UDP_PORT,"radius-proxy"); proxyacctfd = open_udpsock(&radpracct_port,PW_PROXYACCT_UDP_PORT,"radacct-proxy"); if (ipassinit() != 0) { log_err("ipass not in use\n"); }#ifdef ACTIVCARD /* establish aeg session before attending to any user requests */ if (activcard_init() < 0) { log_err("activcard not in use\n"); }#endif update_clients(); update_proxy();#ifdef VPORTS vports_flag = vports_init(); if (vports_flag == 1 && spawn_flag == 1) { spawn_flag = 0; debug("virtual ports disable spawning\n"); }#endif /* VPORTS */ /* * If we are able to spawn processes, we will start a child * to listen for Accounting-Requests. If not, we will * listen for them ourself. */ if(spawn_flag) { acct_pid = fork(); if(acct_pid < 0) { log_err("could not fork to spawn accounting daemon\n"); rad_exit(-1); } if(acct_pid > 0) { close(acctfd); acctfd = -1; close(proxyacctfd); proxyacctfd = -1; } else { close(sockfd); sockfd = -1; close(proxyfd); proxyfd = -1; } } then = 0; /* * Receive user requests */ for(;;) { FD_ZERO(&readfds); if(sockfd >= 0) { FD_SET(sockfd, &readfds); } if(proxyfd >= 0) { FD_SET(proxyfd, &readfds); } if(acctfd >= 0) { FD_SET(acctfd, &readfds); } if(proxyacctfd >= 0) { FD_SET(proxyacctfd, &readfds); } status = select(32, &readfds, NULL, NULL, (struct timeval *)NULL); if(status == -1) { if (errno == EINTR) continue; log_err("exiting after select returned error %d, %s\n",errno,strerror(errno)); sig_fatal(101); } now = (UINT4)time((time_t *)NULL); if (now > then) { then = now; if(sockfd != -1) { update_clients(); } update_proxy(); } if(proxyfd >=0 && FD_ISSET(proxyfd, &readfds)) { rad_proxy(proxyfd); report[RR_PORT3]++; } if(sockfd >= 0 && FD_ISSET(sockfd, &readfds)) { rad_request(sockfd); report[RR_PORT1]++; } if(proxyacctfd >=0 && FD_ISSET(proxyacctfd, &readfds)) { rad_proxy(proxyacctfd); report[RR_PORT4]++; } if(acctfd >=0 && FD_ISSET(acctfd, &readfds)) { rad_acctreq(acctfd); report[RR_PORT2]++; } }}/************************************************************************* * * Function: open_udpsock * * Purpose: open desired UDP socket and return file descripter * Exit program if socket is unavailable * place port number used in first argument * *************************************************************************/int open_udpsock(u_short *port,int defport,char *service){ int fd; int result; struct servent *svp; struct sockaddr_in *sin; struct sockaddr_in salocal; u_short lport; if (*port>5) { lport = htons(*port); } else { svp = getservbyname(service, "udp"); if (svp != (struct servent *) NULL) { lport = (u_short) svp->s_port; } else { lport = htons(defport); } *port = ntohs(lport); } debug("using udp port %d for %s\n", *port,service); fd = socket (AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err("%s socket error %s\n", service, strerror(errno)); rad_exit(-1); } sin = (struct sockaddr_in *) & salocal; memset ((char *) sin, '\0', sizeof (salocal)); sin->sin_family = AF_INET; if (sockaddr != 0) { sin->sin_addr.s_addr = htonl(sockaddr); } else { sin->sin_addr.s_addr = INADDR_ANY; } sin->sin_port = lport; result = bind (fd, (struct sockaddr *)&salocal, sizeof (*sin)); if (result < 0) { log_err("%s bind error %s\n", service, strerror(errno)); rad_exit(-1); } return fd;}/************************************************************************* * * Function: send_packet * * Purpose: Send RADIUS UDP packet * *************************************************************************/void send_packet(int fd, UINT4 ipaddr, u_short port, char * buffer, int length){ AUTH_HDR *auth; struct sockaddr_in saremote; struct sockaddr_in *sin; sin = (struct sockaddr_in *) &saremote; memset ((char *) sin, '\0', sizeof (saremote)); sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(ipaddr); sin->sin_port = htons(port); auth = (AUTH_HDR *)buffer; debug("message sent to %s/%d.%d code=%d, length=%d\n", ipaddr2strp(ipaddr), port, auth->id, auth->code, length); if (debug_flag > 1) { hexdump((u_char*)buffer,length); } /* Send it */ sendto(fd, buffer, (int)length, (int)0, (struct sockaddr *)&saremote, sizeof(struct sockaddr_in));}/************************************************************************* * * Function: rad_request * * Purpose: Receive UDP client requests * *************************************************************************/void rad_request(int fd){ AUTH_REQ *authreq; UINT4 addr; char secret[20]; char hostnm[128]; int result; size_t salen; struct sockaddr_in *sin; u_short port;#if defined(SMARTCARD) int child_pid; AUTH_HDR *auth; AUTH_REQ *curreq; VALUE_PAIR *pair; key_t msg_key;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -