📄 radiud.mp.c
字号:
/*
* RADIUS
* Remote Authentication Dial In User Service
*
*/
static char sccsid[] =
"@(#)radiusd.c 2.0 Copyright 2000 Xiang Tiansheng";
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <fcntl.h>
#include <pwd.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
#if !defined(NOSHADOW)
#include <shadow.h>
#endif /* !NOSHADOW */
#include "radius.h"
#include "account.h"
char recv_buffer[4096];
char send_buffer[4096];
char *progname;
int sockfd;
int acctfd;
int debug_flag;
int spawn_flag;
int acct_pid;
char *radius_dir;
char *radacct_dir;
UINT4 expiration_seconds;
UINT4 warning_seconds;
extern int errno;
static AUTH_REQ *first_request;
REALM_STRUCT *first_realm;
CLIENT_STRUCT *first_client;
USER_ONLINE *first_online_user;
void sig_fatal();
void sig_hup();
void sig_cleanup();
void rad_passchange();
main(argc, argv)
int argc;
char **argv;
{
int salen;
int result;
struct sockaddr salocal;
struct sockaddr saremote;
struct sockaddr_in *sin;
struct servent *svp;
u_short lport;
AUTH_REQ *authreq;
AUTH_REQ *radrecv();
char argval;
int t;
int pid;
int cons;
fd_set readfds;
int status;
int reply_code;
int auth__client();
void send_reply_to_client();
progname = *argv++;
argc--;
debug_flag = 0;
spawn_flag = 1;
radacct_dir = RADACCT_DIR;
radius_dir = RADIUS_DIR;
signal(SIGHUP, sig_hup);
signal(SIGINT, sig_fatal);
signal(SIGQUIT, sig_fatal);
signal(SIGILL, sig_fatal);
signal(SIGTRAP, sig_fatal);
signal(SIGIOT, sig_fatal);
signal(SIGFPE, sig_fatal);
signal(SIGTERM, sig_fatal);
signal(SIGCHLD, sig_cleanup);
while(argc) {
if(**argv != '-') {
usage();
}
argval = *(*argv + 1);
argc--;
argv++;
switch(argval) {
case 'a':
if(argc == 0) {
usage();
}
radacct_dir = *argv;
argc--;
argv++;
break;
case 'd':
if(argc == 0) {
usage();
}
radius_dir = *argv;
argc--;
argv++;
break;
case 's': /* Single process mode */
spawn_flag = 0;
break;
case 'v':
version();
break;
case 'x':
debug_flag = 1;
break;
default:
usage();
break;
}
}
/* Initialize the dictionary */
if(dict_init() != 0) {
exit(-1);
}
/* Initialize the realms */
if(client_realm_init() != 0) {
exit(-1);
}
/* Mallocate a cache to init the online user record */
if(user_online_init() != 0) {
exit(-1);
}
/* Initialize Configuration Values */
if(config_init() != 0) {
exit(-1);
}
svp = getservbyname ("radius", "udp");
if (svp == (struct servent *) 0) {
fprintf (stderr, "%s: No such service: radius/udp\n",
progname);
exit(-1);
}
lport = (u_short) svp->s_port;
sockfd = socket (AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
(void) perror ("auth socket");
exit(-1);
}
sin = (struct sockaddr_in *) & salocal;
memset ((char *) sin, '\0', sizeof (salocal));
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = lport;
result = bind (sockfd, & salocal, sizeof (*sin));
if (result < 0) {
(void) perror ("auth bind");
exit(-1);
}
/*
* Open Accounting Socket.
*/
/* svp = getservbyname ("radacct", "udp");
if (svp == (struct servent *) 0) {
fprintf (stderr, "%s: No such service: %s/%s\n",
progname, "radacct", "udp");
exit(-1);
} */
lport = htons(ntohs(lport) +1);
acctfd = socket (AF_INET, SOCK_DGRAM, 0);
if (acctfd < 0) {
(void) perror ("acct socket");
exit(-1);
}
sin = (struct sockaddr_in *) & salocal;
memset ((char *) sin, '\0', sizeof (salocal));
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = lport;
result = bind (acctfd, & salocal, sizeof (*sin));
if (result < 0) {
(void) perror ("acct bind");
exit(-1);
}
/*
* Disconnect from session
*/
if(debug_flag == 0) {
pid = fork();
if(pid < 0) {
fprintf(stderr, "%s: Couldn't fork\n",
progname);
exit(-1);
}
if(pid > 0) {
exit(0);
}
}
/*
* Disconnect from tty
*/
for (t = 32; t >= 3; t--) {
if(t != sockfd && t != acctfd) {
close(t);
}
}
#if !defined(M_UNIX)
/*
* Open system console as stderr
*/
cons = open("/dev/console", O_WRONLY | O_NOCTTY);
if(cons != 2) {
dup2(cons, 2);
close(cons);
}
#endif
/*
* 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) {
fprintf(stderr, "%s: Couldn't fork\n",
progname);
exit(-1);
}
if(acct_pid > 0) {
close(acctfd);
acctfd = -1;
}
else {
close(sockfd);
sockfd = -1;
}
}
*/
/*
* Receive user requests
*/
sin = (struct sockaddr_in *) & saremote;
for(;;) {
FD_ZERO(&readfds);
if(sockfd >= 0) {
FD_SET(sockfd, &readfds);
}
if(acctfd >= 0) {
FD_SET(acctfd, &readfds);
}
status = select(32, &readfds, NULL, NULL, NULL);
if(status == -1) {
if (errno == EINTR)
continue;
sig_fatal(101);
}
if(sockfd >= 0 && FD_ISSET(sockfd, &readfds)) {
salen = sizeof (saremote);
result = recvfrom (sockfd, (char *) recv_buffer,
(int) sizeof(recv_buffer),
(int) 0, & saremote, & salen);
if(result > 0) {
#ifdef CHECK_KNOWNCLIENT
if(!knownclient(ntohl(sin->sin_addr.s_addr))) {
/* packet, meet floor */
char lbuf[128];
sprintf(lbuf, "Unknown Client - %s",
inet_ntoa(sin->sin_addr));
log_err(lbuf);
continue;
}
#endif
authreq = radrecv(
ntohl(sin->sin_addr.s_addr),
ntohs(sin->sin_port),
recv_buffer, result, sockfd);
if(auth_client(authreq) == 0){
radrespond(authreq, sockfd);
}else{ reply_code = PW_AUTHENTICATION_REJECT;
send_reply_to_client(authreq,(char *)NULL,sockfd,reply_code);
}
}
else if(result < 0 && errno == EINTR) {
result = 0;
}
}
if(acctfd >=0 && FD_ISSET(acctfd, &readfds)) {
salen = sizeof (saremote);
result = recvfrom (acctfd, (char *) recv_buffer,
(int) sizeof(recv_buffer),
(int) 0, & saremote, & salen);
if(result > 0) {
authreq = radrecv(
ntohl(sin->sin_addr.s_addr),
ntohs(sin->sin_port),
recv_buffer, result, acctfd);
if(auth_client(authreq) == 0) {
radrespond(authreq, acctfd);
}else{ reply_code = PW_ACCOUNTING_RESPONSE;
send_reply_to_client(authreq,(char *)NULL,acctfd,reply_code);
}
}
else if(result < 0 && errno == EINTR) {
result = 0;
}
}
}
}
/*************************************************************************
*
* Function: radrecv
*
* Purpose: Receive UDP client requests, build an authorization request
* structure, and attach attribute-value pairs contained in
* the request to the new structure.
*
*************************************************************************/
AUTH_REQ *
radrecv(host, udp_port, buffer, length, activefd)
UINT4 host;
u_short udp_port;
u_char *buffer;
int length;
int activefd;
{
u_char *ptr;
AUTH_HDR *auth;
int totallen;
int attribute;
int attrlen;
DICT_ATTR *attr;
DICT_ATTR *dict_attrget();
char string[64];
UINT4 lvalue;
char *ip_hostname();
VALUE_PAIR *first_pair;
VALUE_PAIR *prev;
VALUE_PAIR *pair;
AUTH_REQ *authreq;
/*
* Pre-allocate the new request data structure
*/
if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) ==
(AUTH_REQ *)NULL) {
fprintf(stderr, "%s: no memory\n", progname);
exit(-1);
}
auth = (AUTH_HDR *)buffer;
totallen = ntohs(auth->length);
DEBUG("radrecv: Request from host %lx code=%d, id=%d, length=%d\n",
(u_long)host, auth->code, auth->id, totallen);
/*
* Fill header fields
*/
authreq->ipaddr = host;
authreq->udp_port = udp_port;
authreq->id = auth->id;
authreq->code = auth->code;
authreq->proxy_state = 0;
memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);
/*
* Extract attribute-value pairs
*/
ptr = auth->data;
length -= AUTH_HDR_LEN;
first_pair = (VALUE_PAIR *)NULL;
prev = (VALUE_PAIR *)NULL;
while(length > 0) {
attribute = *ptr++;
attrlen = *ptr++;
if(attrlen < 2) {
length = 0;
continue;
}
attrlen -= 2;
if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
DEBUG("Received unknown attribute %d\n", attribute);
}
else if ( attrlen >= AUTH_STRING_LEN ) {
DEBUG("attribute %d too long, %d >= %d\n", attribute,
attrlen, AUTH_STRING_LEN);
}
else {
if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
(VALUE_PAIR *)NULL) {
fprintf(stderr, "%s: no memory\n",
progname);
exit(-1);
}
strcpy(pair->name, attr->name);
pair->attribute = attr->value;
pair->type = attr->type;
pair->next = (VALUE_PAIR *)NULL;
switch(attr->type) {
case PW_TYPE_STRING:
memcpy(pair->strvalue, ptr, attrlen);
pair->strvalue[attrlen] = '\0';
debug_pair(stdout, pair);
if(first_pair == (VALUE_PAIR *)NULL) {
first_pair = pair;
}
else {
prev->next = pair;
}
prev = pair;
break;
case PW_TYPE_INTEGER:
case PW_TYPE_IPADDR:
memcpy(&lvalue, ptr, sizeof(UINT4));
pair->lvalue = ntohl(lvalue);
debug_pair(stdout, pair);
if(first_pair == (VALUE_PAIR *)NULL) {
first_pair = pair;
}
else {
prev->next = pair;
}
prev = pair;
break;
default:
DEBUG(" %s (Unknown Type %d)\n", attr->name,attr->type);
free(pair);
break;
}
}
ptr += attrlen;
length -= attrlen + 2;
}
authreq->request = first_pair;
return(authreq);
}
/**************** function multi_thre(authreq,activefd) ***************/
multi_thre(authreq,activefd)
AUTH_REQ *authreq;
int activefd;
{
int reply_code;
switch(authreq->code) {
case PW_AUTHENTICATION_REQUEST:
rad_authenticate(authreq, activefd);
break;
case PW_ACCOUNTING_REQUEST:
rad_accounting(authreq, activefd);
break;
#ifdef PASSCHANGE
case PW_PASSWORD_REQUEST:
rad_passchange(authreq, activefd);
break;
#endif
default:
break;
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -