sendserver.c
来自「RADIUS协议的认证计费服务」· C语言 代码 · 共 939 行 · 第 1/2 页
C
939 行
/* * Copyright [C] The Regents of the University of Michigan and Merit Network, * Inc. 1992, 1993, 1994, 1995, 1996, 1997, 1998 All Rights Reserved * * Permission to use, copy, and modify this software and its documentation * for any purpose and without fee is hereby granted, provided: * * 1) that the above copyright notice and this permission notice appear in all * copies of the software and derivative works or modified versions thereof, * * 2) that both the copyright notice and this permission and disclaimer notice * appear in all supporting documentation, and * * 3) that all derivative works made from this material are returned to the * Regents of the University of Michigan and Merit Network, Inc. with * permission to copy, to display, to distribute, and to make derivative * works from the provided material in whole or in part for any purpose. * * Users of this code are requested to notify Merit Network, Inc. of such use * by sending email to aaa-admin@merit.edu * * Please also use aaa-admin@merit.edu to inform Merit Network, Inc of any * derivative works. * * Distribution of this software or derivative works or the associated * documentation is not allowed without an additional license. * * Licenses for other uses are available on an individually negotiated * basis. Contact aaa-license@merit.edu for more information. * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the * University of Michigan and Merit Network, Inc. shall not be liable for any * special, indirect, incidental or consequential damages with respect to any * claim by Licensee or any third party arising from use of the software. * * Merit AAA Server Support * Merit Network, Inc. * 4251 Plymouth Road, Suite C. * Ann Arbor, Michigan, USA 48105-2785 * * attn: John Vollbrecht * voice: 734-764-9430 * fax: 734-647-3185 * email: aaa-admin@merit.edu * *//* * * Public entry points in this file: * * dir_init * send_server * send_server_done * */static char rcsid[] = "$Id: sendserver.c,v 1.1.1.1 2001/08/10 20:49:29 bonze Exp $";#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/param.h>#include <sys/time.h>#if !(defined(FD_SET) || defined(linux))#include <sys/select.h>#endif /* FD_SET */#include <errno.h>#include <memory.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <syslog.h>#include <unistd.h>#include "radius.h"#if !defined(__FreeBSD__) && !defined(_BSDI_VERSION) && !defined(__NetBSD__)/* commented by bonzeextern char *sys_errlist[];*/extern __const char *__const _sys_errlist[];#endif /* __FreeBSD__ */#ifndef DEFAULT_SERVER#define DEFAULT_SERVER "127.0.0.1"#endif#ifndef DEFAULT_DIR#define DEFAULT_DIR "../config"#endif#ifndef DEFAULT_DIR2#define DEFAULT_DIR2 "../config"#endif#ifndef DEFAULT_VERSION#define DEFAULT_VERSION 1#endifextern UINT2 send_buffer_size;extern char recv_buffer[RAD_RECV_BUFFER_SIZE];extern char send_buffer[RAD_SEND_BUFFER_SIZE];extern char ourhostname[MAXHOSTNAMELEN];extern char *progname;extern int debug_flag;extern char *radius_dir;int radsock = -1; /* fd for radius socket, if non-blocking mode */static int sockfd = -1;static int check_radius_reply PROTO((u_char *, u_int, char *, u_char *, UINT4, SEND_DATA *, char *));static int find_server PROTO((char *, int, UINT4 *, char *, char *));/************************************************************************* * * Function: dir_init * * Purpose: Initializes global variable for RADIUS clients. * **************************************************************************/voiddir_init (){ if (radius_dir == NULL || radius_dir[0] == '\0') { radius_dir = DEFAULT_DIR; if (access (radius_dir, X_OK) != 0) { radius_dir = DEFAULT_DIR2; } } return;} /* end of dir_init () *//************************************************************************* * * Function: pack_list * * Purpose: Packs an attribute value pair list into a buffer. * * Returns: Number of octets packed. * *************************************************************************/static voidpack_list (vp, auth)VALUE_PAIR *vp;AUTH_HDR *auth;{ while (vp != NULL_VP) { avpair_out (vp, auth, send_buffer_size, (VENDOR_LIST *) NULL); vp = vp->next; } return;} /* end of pack_list () *//************************************************************************* * * Function: send_server * * Purpose: Sends request to specified RADIUS server and waits * for response. Request is retransmitted every * "response_timeout" seconds a maximum of "retry_max" * times. Result is 0 if response was received, -1 if * a problem occurred, or +1 on no-response condition. * Returns request retransmit count in "retries" if * server does respond. * * Returns: -1 ERROR_RC -- on local error, * 0 OK_RC -- on valid response from server, * 1 TIMEOUT_RC -- after retries * resp_timeout seconds, * -2 BADRESP_RC -- if response from server had errors. * **************************************************************************/int send_server (data, retries, msg)SEND_DATA *data; /* Data structure built by clients */int *retries; /* Maximum num of times to retransmit request */ /* Receives number of retries required, also */char *msg; /* Receives error or advisory message */{ u_short seq_nbr; /* Sequence number to use in request */ u_int length; int fptype; /* Framed proto, ustype == PW_FRAMED */ int i; int len; int result; int retry_max; int salen; int timeout; /* Number of secs. to wait for response */ int total_length; int ustype; /* User service type for this user */ int version; UINT4 auth_ipaddr; UINT4 lvalue; AUTH_HDR *auth; VALUE_PAIR *check; VALUE_PAIR *reply; char *passwd; /* User password (unencrypted) */ char *server_name; /* Name of server to query */ char *vector; struct sockaddr_in *sin; struct servent *svp; struct timeval authtime; fd_set readfds; struct sockaddr salocal; struct sockaddr saremote; char ara_vector[ARA_PASS_LEN + 1]; char file[MAXPATHLEN]; char secret[MAX_SECRET_LENGTH + 1]; char chap_auth; u_char md5buf[1 + AUTH_VECTOR_LEN]; u_char buffer[AUTH_PASS_LEN + AUTH_VECTOR_LEN + 1];#if 0 /* Don't really do KCHAP */ u_char user_secret[CHAP_VALUE_LENGTH + 1];#endif /* Do CHAP instead */ static char *func = "send_server"; /* Set up some defaults */ dir_init (); server_name = data->server; if (server_name == (char *) NULL || server_name[0] == '\0') { server_name = DEFAULT_SERVER; } ustype = data->ustype; if (ustype == 255) /* CHAP indicator */ { chap_auth = 1; ustype = PW_FRAMED; } else { chap_auth = 0; } if (find_server (server_name, ustype, &auth_ipaddr, secret, msg) != 0) { return (ERROR_RC); } timeout = data->timeout; if (timeout == 0) { timeout++; } if (data->svc_port == 0) { if ((svp = getservbyname ("radius", "udp")) == NULL) { data->svc_port = PW_AUTH_UDP_PORT; } else { data->svc_port = ntohs(svp->s_port); } } if (sockfd < 0) { if (radsock < 0) { if (sockfd < 0) { sockfd = socket (AF_INET, SOCK_DGRAM, 0); } if (sockfd < 0) { sprintf (msg, "socket: %s\n", sys_errlist[errno]); return (ERROR_RC); } len = sizeof (salocal); sin = (struct sockaddr_in *) & salocal; memset ((char *) sin, '\0', len); sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; sin->sin_port = htons(0); if (bind (sockfd, (struct sockaddr *) sin, len) < 0 || getsockname (sockfd, (struct sockaddr *) sin, &len) < 0) { /* XXX close (sockfd); */ sprintf (msg, "bind: %s\n", sys_errlist[errno]); return (ERROR_RC); } retry_max = *retries; /* Max. times to try for reply */ *retries = 0; /* Init retry cnt for blocking call */ } else { sockfd = radsock; retry_max = 0; /* No retries if non-blocking */ } } /* Build an authentication request */ auth = (AUTH_HDR *) send_buffer; seq_nbr = data->seq_nbr; if ((version = data->version) == 0) { version = DEFAULT_VERSION; } vector = build_header (version, (char *) NULL, data->code, seq_nbr, auth, (CLIENT_ENTRY *) NULL); /* User Name */ if (data->user_name != (char *) NULL) { len = strlen (data->user_name); if (len > AUTH_ID_LEN) { len = AUTH_ID_LEN; } attribute_out (auth, send_buffer_size, PW_USER_NAME, 0, data->user_name, len, 0, (VENDOR_LIST *) NULL); } passwd = data->password; if ((data->code != PW_ACCOUNTING_REQUEST) && (passwd != (char *) NULL)) { if (chap_auth) { /* User Password */ *md5buf = seq_nbr; /* Pass CHAP identifier to RADIUS */ *buffer = seq_nbr;/* Put CHAP id in work area for md5 */#if 0 /* Don't really do KCHAP */ afs_pwd_to_secret (passwd, user_secret);/* Get secret */ passwd = user_secret;#endif /* Do CHAP instead */ len = strlen (passwd); strcpy ((char *) buffer + 1, (char *) passwd); memcpy ((char *) buffer + 1 + len, (char *) vector, AUTH_VECTOR_LEN); md5_calc (md5buf + 1, buffer, 1 + len + AUTH_VECTOR_LEN); attribute_out (auth, send_buffer_size, PW_CHAP_PASSWORD, 0, md5buf, AUTH_VECTOR_LEN + 1, 0, (VENDOR_LIST *) NULL); }#ifdef ASCEND else if (data->arades == 1) { length = strlen (passwd); if (length > ARA_PASS_LEN) { length = ARA_PASS_LEN; } for (i = 0; i < length; ++i) { passwd[i] = (u_char) (passwd[i] <<1); } if (des_init ()) { /* XXX close (sockfd); */ sprintf (msg, "des_init: Can't initialize"); return (ERROR_RC); } dessetkey ((char *)passwd); memcpy (ara_vector, vector, ARA_PASS_LEN); endes (ara_vector); attribute_out (auth, send_buffer_size, PW_ASCEND_ARADES, VC_ASCEND, ara_vector, ARA_PASS_LEN, 0, (VENDOR_LIST *) NULL); desdone (); }#endif /* ASCEND */ else { attribute_pw_out (auth, send_buffer_size, passwd, secret); } } /* State */ if (data->challenge > 0) /* Add zero length state */ { attribute_out (auth, send_buffer_size, PW_STATE, 0, "", 0, 0, (VENDOR_LIST *) NULL); } /* Service Type */ if (ustype != -1) { lvalue = ustype; attribute_out (auth, send_buffer_size, PW_SERVICE_TYPE, 0, &lvalue, 0, 0, (VENDOR_LIST *) NULL); } /* Framed Protocol Type */ fptype = data->fptype; if (fptype > 0) /* if -t [slip | ppp] */ { lvalue = fptype; attribute_out (auth, send_buffer_size, PW_FRAMED_PROTOCOL, 0, &lvalue, 0, 0, (VENDOR_LIST *) NULL); } /* Client IP Address */ if (data->client_id != (UINT4) -1) { attribute_out (auth, send_buffer_size, PW_NAS_IP_ADDRESS, 0, &data->client_id, 0, 0, (VENDOR_LIST *) NULL); } /* Client Port Number */ if (data->port_num != -1) { lvalue = data->port_num; attribute_out (auth, send_buffer_size, PW_NAS_PORT, 0, &lvalue, 0, 0, (VENDOR_LIST *) NULL); } if (data->user_file != (char *) NULL) /* add a/v pairs from user_file */ { sprintf (file, "%s.", data->user_file); check = NULL_VP; if ((user_find (file, data->group, 0, &check, (VALUE_PAIR **) NULL, &reply, 1)) == 0) { pack_list (check, auth); pack_list (reply, auth); } } if (data->send_pairs != NULL_VP) /* add more a/v pairs */ { pack_list (data->send_pairs, auth); } total_length = (u_short) build_request_mic (auth, secret); sin = (struct sockaddr_in *) & saremote; memset ((char *) sin, '\0', sizeof (saremote));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?