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

📄 radiusd.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	DEBUG2("rad_lowerpair:  %s now '%s'", vp->name, vp->strvalue);	return 0;}/* *  Remove spaces in a pair. */static int rad_rmspace_pair(REQUEST *request UNUSED, VALUE_PAIR *vp) {	if (vp == NULL) {		return -1;	}	rad_rmspace((char *)vp->strvalue);	vp->length = strlen((char *)vp->strvalue);	DEBUG2("rad_rmspace_pair:  %s now '%s'", vp->name, vp->strvalue);	return 0;}/* *  Respond to a request packet. * *  Maybe we reply, maybe we don't. *  Maybe we proxy the request to another server, or else maybe *  we replicate it to another server. */int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun){	RADIUS_PACKET *packet, *original;	const char *secret;	int finished = FALSE;	int reprocess = 0;	rad_assert(request->magic == REQUEST_MAGIC);	/*	 *	Don't decode the packet if it's an internal "fake"	 *	request.  Instead, just skip ahead to processing it.	 */	if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {		goto skip_decode;	}	/*	 *  Put the decoded packet into it's proper place.	 */	if (request->proxy_reply != NULL) {		packet = request->proxy_reply;		secret = request->proxysecret;		original = request->proxy;	} else {		packet = request->packet;		secret = request->secret;		original = NULL;	}	/*	 *  Decode the packet, verifying it's signature,	 *  and parsing the attributes into structures.	 *	 *  Note that we do this CPU-intensive work in	 *  a child thread, not the master.  This helps to	 *  spread the load a little bit.	 *	 *  Internal requests (ones that never go on the	 *  wire) have ->data==NULL (data is the wire	 *  format) and don't need to be "decoded"	 */	if (packet->data && rad_decode(packet, original, secret) != 0) {		radlog(L_ERR, "%s", librad_errstr);		request_reject(request);		goto finished_request;	}	/*	 *  For proxy replies, remove non-allowed	 *  attributes from the list of VP's.	 */	if (request->proxy) {		int rcode;		rcode = proxy_receive(request);		switch (rcode) {                default:  /* Don't Do Anything */			break;                case RLM_MODULE_FAIL:			/* on error just continue with next request */			goto next_request;                case RLM_MODULE_HANDLED:			/* if this was a replicated request, mark it as			 * finished first, because it was postponed			 */			goto finished_request;		}	} else {		/*		 *	This is the initial incoming request which		 *	we're processing.		 *		 *	Some requests do NOT get cached, as they		 *	CANNOT possibly have duplicates.  Set the		 *	magic option here.		 *		 *	Status-Server messages are easy to generate,		 *	so we toss them as soon as we see a reply.		 *		 *	Accounting-Request packets WITHOUT an		 *	Acct-Delay-Time attribute are NEVER		 *	duplicated, as RFC 2866 Section 4.1 says that		 *	the Acct-Delay-Time MUST be updated when the		 *	packet is re-sent, which means the packet		 *	changes, so it MUST have a new identifier and		 *	Request Authenticator.  */		if ((request->packet->code == PW_STATUS_SERVER) ||		    ((request->packet->code == PW_ACCOUNTING_REQUEST) &&		     (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {			request->options |= RAD_REQUEST_OPTION_DONT_CACHE;		}	} skip_decode:	/*	 *	We should have a User-Name attribute now.	 */	if (request->username == NULL) {		request->username = pairfind(request->packet->vps,				PW_USER_NAME);	}	/*	 *  FIXME:  All this lowercase/nospace junk will be moved	 *  into a module after module failover is fully in place	 *	 *  See if we have to lower user/pass before processing	 */	if(strcmp(mainconfig.do_lower_user, "before") == 0)		rad_lowerpair(request, request->username);	if(strcmp(mainconfig.do_lower_pass, "before") == 0)		rad_lowerpair(request,			      pairfind(request->packet->vps, PW_PASSWORD));	if(strcmp(mainconfig.do_nospace_user, "before") == 0)		rad_rmspace_pair(request, request->username);	if(strcmp(mainconfig.do_nospace_pass, "before") == 0)		rad_rmspace_pair(request,				 pairfind(request->packet->vps, PW_PASSWORD));	(*fun)(request);	/*	 *	If the request took too long to process, don't do	 *	anything else.	 */	if (request->options & RAD_REQUEST_OPTION_REJECTED) {		finished = TRUE;		goto postpone_request;	}	/*	 *	Reprocess if we rejected last time	 */	if ((fun == rad_authenticate) &&	    (request->reply->code == PW_AUTHENTICATION_REJECT)) {	  /* See if we have to lower user/pass after processing */	  if (strcmp(mainconfig.do_lower_user, "after") == 0) {		  rad_lowerpair(request, request->username);		  reprocess = 1;	  }	  if (strcmp(mainconfig.do_lower_pass, "after") == 0) {		rad_lowerpair(request,			      pairfind(request->packet->vps, PW_PASSWORD));		reprocess = 1;	  }	  if (strcmp(mainconfig.do_nospace_user, "after") == 0) {		  rad_rmspace_pair(request, request->username);		  reprocess = 1;	  }	  if (strcmp(mainconfig.do_nospace_pass, "after") == 0) {		  rad_rmspace_pair(request,				   pairfind(request->packet->vps, PW_PASSWORD));		  reprocess = 1;	  }	  /*	   *	If we're re-processing the request, re-set it.	   */	  if (reprocess) {		  pairfree(&request->config_items);		  pairfree(&request->reply->vps);		  request->reply->code = 0;		  (*fun)(request);	  }	}	/*	 *	Status-Server requests NEVER get proxied.	 */	if (mainconfig.proxy_requests) {		if ((request->packet->code != PW_STATUS_SERVER) &&		    ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {			int rcode;			/*			 *	Try to proxy this request.			 */			rcode = proxy_send(request);			switch (rcode) {			default:				break;			/*			 *  There was an error trying to proxy the request.			 *  Drop it on the floor.			 */			case RLM_MODULE_FAIL:				DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);				request_reject(request);				goto finished_request;				break;			/*			 *  The pre-proxy module has decided to reject			 *  the request.  Do so.			 */			case RLM_MODULE_REJECT:				DEBUG2("Request %d rejected in proxy_send.", request->number);				request_reject(request);				goto finished_request;				break;			/*			 *  If the proxy code has handled the request,			 *  then postpone more processing, until we get			 *  the reply packet from the home server.			 */			case RLM_MODULE_HANDLED:				goto postpone_request;				break;			}			/*			 *  Else rcode==RLM_MODULE_NOOP			 *  and the proxy code didn't do anything, so			 *  we continue handling the request here.			 */		}	} else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&		   (request->reply->code == 0)) {		/*		 *  We're not configured to reply to the packet,		 *  and we're not proxying, so the DEFAULT behaviour		 *  is to REJECT the user.		 */		DEBUG2("There was no response configured: rejecting request %d", request->number);		request_reject(request);		goto finished_request;	}	/*	 *  If we have a reply to send, copy the Proxy-State	 *  attributes from the request to the tail of the reply,	 *  and send the packet.	 */	rad_assert(request->magic == REQUEST_MAGIC);	if (request->reply->code != 0) {		VALUE_PAIR *vp = NULL;		/*		 *	Perform RFC limitations on outgoing replies.		 */		rfc_clean(request->reply);		/*		 *	Need to copy Proxy-State from request->packet->vps		 */		vp = paircopy2(request->packet->vps, PW_PROXY_STATE);		if (vp) pairadd(&(request->reply->vps), vp);		/*		 *  If the request isn't an authentication reject, OR		 *  it's a reject, but the reject_delay is zero, then		 *  send it immediately.		 *		 *  Otherwise, delay the authentication reject to shut		 *  up DoS attacks.		 */		if ((request->reply->code != PW_AUTHENTICATION_REJECT) ||		    (mainconfig.reject_delay == 0)) {			/*			 *	Send the response. IF it's a real request.			 */			if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0) {				rad_send(request->reply, request->packet,					 request->secret);			}			/*			 *	Otherwise, it's a tunneled request.			 *	Don't do anything.			 */		} else {			DEBUG2("Delaying request %d for %d seconds",			       request->number, mainconfig.reject_delay);			request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;		}	}	/*	 *  We're done processing the request, set the	 *  request to be finished, clean up as necessary,	 *  and forget about the request.	 */finished_request:	/*	 *	Don't decode the packet if it's an internal "fake"	 *	request.  Instead, just skip ahead to processing it.	 */	if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {		goto skip_free;	}	/*	 *  We're done handling the request.  Free up the linked	 *  lists of value pairs.  This might take a long time,	 *  so it's more efficient to do it in a child thread,	 *  instead of in the main handler when it eventually	 *  gets around to deleting the request.	 *	 *  Also, no one should be using these items after the	 *  request is finished, and the reply is sent.  Cleaning	 *  them up here ensures that they're not being used again.	 *	 *  Hmm... cleaning them up in the child thread also seems	 *  to make the server run more efficiently!	 *	 *  If we've delayed the REJECT, then do NOT clean up the request,	 *  as we haven't created the REJECT message yet.	 */	if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {		if (request->packet) {			pairfree(&request->packet->vps);			request->username = NULL;			request->password = NULL;		}		/*		 *  If we've sent a reply to the NAS, then this request is		 *  pretty much finished, and we have no more need for any		 *  of the value-pair's in it, including the proxy stuff.		 */		if (request->reply->code != 0) {			pairfree(&request->reply->vps);		}	}	pairfree(&request->config_items);	if (request->proxy) {		pairfree(&request->proxy->vps);	}	if (request->proxy_reply) {		pairfree(&request->proxy_reply->vps);	} skip_free:	DEBUG2("Finished request %d", request->number);	finished = TRUE;	/*	 *  Go to the next request, without marking	 *  the current one as finished.	 *	 *  Hmm... this may not be the brightest thing to do.	 */next_request:	DEBUG2("Going to the next request");postpone_request:#ifdef HAVE_PTHREAD_H	/*	 *  We are finished with the child thread.  The thread is detached,	 *  so that when it exits, there's nothing more for the server	 *  to do.	 *	 *  If we're running with thread pools, then this frees up the	 *  thread in the pool for another request.	 */	request->child_pid = NO_SUCH_CHILD_PID;#endif	request->finished = finished; /* do as the LAST thing before exiting */	return 0;}/* *  Display the syntax for starting this program. */static void usage(int status){	FILE *output = status?stderr:stdout;	fprintf(output,			"Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-AcfnsSvXxyz]\n", progname);	fprintf(output, "Options:\n\n");	fprintf(output, "  -a acct_dir     use accounting directory 'acct_dir'.\n");	fprintf(output, "  -A              Log auth detail.\n");	fprintf(output, "  -d db_dir       Use database directory 'db_dir'.\n");	fprintf(output, "  -f              Run as a foreground process, not a daemon.\n");	fprintf(output, "  -h              Print this help message.\n");	fprintf(output, "  -i address      Listen only in the given IP address.\n");	fprintf(output, "  -l log_dir      Log messages to 'log_dir'.  Special values are:\n");	fprintf(output, "                  stdout == log all messages to standard output.\n");	fprintf(output, "                  syslog == log all messages to the system logger.\n");	fprintf(output, "  -p port         Bind to 'port', and not to the radius/udp, or 1646/udp.\n");	fprintf(output, "  -s              Do not spawn child processes to handle requests.\n");	fprintf(output, "  -S              Log stripped names.\n");	fprintf(output, "  -v              Print server version information.\n");	fprintf(output, "  -X              Turn on full debugging. (Means: -sfxxyz -l stdout)\n");	fprintf(output, "  -x              Turn on partial debugging. (-xx gives more debugging).\n");	fprintf(output, "  -y              Log authentication failures, with password.\n");	fprintf(output, "  -z              Log authentication successes, with password.\n");	exit(status);}/* *	We got a fatal signal. */static void sig_fatal(int sig){	switch(sig) {		case SIGTERM:			do_exit = 1;			break;		default:			do_exit = 2;			break;	}}/* *  We got the hangup signal. *  Re-read the configuration files. *//*ARGSUSED*/static void sig_hup(int sig){	sig = sig; /* -Wunused */	reset_signal(SIGHUP, sig_hup);	/*	 *  Only do the reload if we're the main server, both	 *  for processes, and for threads.	 */	if (getpid() == radius_pid) {		need_reload = TRUE;	}#ifdef WITH_SNMP	if (mainconfig.do_snmp) {		rad_snmp.smux_failures = 0;		rad_snmp.smux_event = SMUX_CONNECT;	}#endif}/* *	Process and reply to a server-status request. *	Like rad_authenticate and rad_accounting this should *	live in it's own file but it's so small we don't bother. */static int rad_status_server(REQUEST *request){	char		reply_msg[64];	time_t		t;	VALUE_PAIR	*vp;	/*	 *	Reply with an ACK. We might want to add some more	 *	interesting reply attributes, such as server uptime.	 */	t = request->timestamp - start_time;	sprintf(reply_msg, "FreeRADIUS up %d day%s, %02d:%02d",		(int)(t / 86400), (t / 86400) == 1 ? "" : "s",		(int)((t / 3600) % 24), (int)(t / 60) % 60);	request->reply->code = PW_AUTHENTICATION_ACK;	vp = pairmake("Reply-Message", reply_msg, T_OP_SET);	pairadd(&request->reply->vps, vp); /* don't need to check if !vp */	return 0;}

⌨️ 快捷键说明

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