mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Merged revisions 312764 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ................ r312764 | mnicholson | 2011-04-05 09:13:07 -0500 (Tue, 05 Apr 2011) | 15 lines Merged revisions 312761 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r312761 | mnicholson | 2011-04-05 09:10:34 -0500 (Tue, 05 Apr 2011) | 8 lines Limit the number of unauthenticated manager sessions and also limit the time they have to authenticate. AST-2011-005 (closes issue #18996) Reported by: tzafrir Tested by: mnicholson ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@312766 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -860,6 +860,8 @@ static const int DEFAULT_DISPLAYCONNECTS	= 1;	/*!< Default setting for displayin | ||||
| static const int DEFAULT_TIMESTAMPEVENTS	= 0;	/*!< Default setting for timestampevents */	 | ||||
| static const int DEFAULT_HTTPTIMEOUT 		= 60;	/*!< Default manager http timeout */ | ||||
| static const int DEFAULT_BROKENEVENTSACTION	= 0;	/*!< Default setting for brokeneventsaction */ | ||||
| static const int DEFAULT_AUTHTIMEOUT		= 30;	/*!< Default setting for authtimeout */ | ||||
| static const int DEFAULT_AUTHLIMIT		= 50;	/*!< Default setting for authlimit */ | ||||
|  | ||||
| static int displayconnects; | ||||
| static int allowmultiplelogin = 1; | ||||
| @@ -868,12 +870,15 @@ static int httptimeout; | ||||
| static int broken_events_action; | ||||
| static int manager_enabled = 0; | ||||
| static int webmanager_enabled = 0; | ||||
| static int authtimeout; | ||||
| static int authlimit; | ||||
| static char *manager_channelvars; | ||||
|  | ||||
| #define DEFAULT_REALM		"asterisk" | ||||
| static char global_realm[MAXHOSTNAMELEN];	/*!< Default realm */ | ||||
|  | ||||
| static int block_sockets; | ||||
| static int unauth_sessions = 0; | ||||
|  | ||||
| static int manager_debug;	/*!< enable some debugging code in the manager */ | ||||
|  | ||||
| @@ -951,6 +956,7 @@ struct mansession_session { | ||||
| 	int send_events;	/*!<  XXX what ? */ | ||||
| 	struct eventqent *last_ev;	/*!< last event processed. */ | ||||
| 	int writetimeout;	/*!< Timeout for ast_carefulwrite() */ | ||||
| 	time_t authstart; | ||||
| 	int pending_event;         /*!< Pending events indicator in case when waiting_thread is NULL */ | ||||
| 	time_t noncetime;	/*!< Timer for nonce value expiration */ | ||||
| 	struct ao2_container *whitefilters; | ||||
| @@ -2935,6 +2941,7 @@ static int action_login(struct mansession *s, const struct message *m) | ||||
| 		return -1; | ||||
| 	} | ||||
| 	s->session->authenticated = 1; | ||||
| 	ast_atomic_fetchadd_int(&unauth_sessions, -1); | ||||
| 	if (manager_displayconnects(s->session)) { | ||||
| 		ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr)); | ||||
| 	} | ||||
| @@ -4522,6 +4529,8 @@ static int get_input(struct mansession *s, char *output) | ||||
| 	int res, x; | ||||
| 	int maxlen = sizeof(s->session->inbuf) - 1; | ||||
| 	char *src = s->session->inbuf; | ||||
| 	int timeout = -1; | ||||
| 	time_t now; | ||||
|  | ||||
| 	/* | ||||
| 	 * Look for \r\n within the buffer. If found, copy to the output | ||||
| @@ -4550,6 +4559,20 @@ static int get_input(struct mansession *s, char *output) | ||||
| 	} | ||||
| 	res = 0; | ||||
| 	while (res == 0) { | ||||
| 		/* calculate a timeout if we are not authenticated */ | ||||
| 		if (!s->session->authenticated) { | ||||
| 			if(time(&now) == -1) { | ||||
| 				ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			timeout = (authtimeout - (now - s->session->authstart)) * 1000; | ||||
| 			if (timeout < 0) { | ||||
| 				/* we have timed out */ | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		ao2_lock(s->session); | ||||
| 		if (s->session->pending_event) { | ||||
| 			s->session->pending_event = 0; | ||||
| @@ -4559,7 +4582,7 @@ static int get_input(struct mansession *s, char *output) | ||||
| 		s->session->waiting_thread = pthread_self(); | ||||
| 		ao2_unlock(s->session); | ||||
|  | ||||
| 		res = ast_wait_for_input(s->session->fd, -1);	/* return 0 on timeout ? */ | ||||
| 		res = ast_wait_for_input(s->session->fd, timeout); | ||||
|  | ||||
| 		ao2_lock(s->session); | ||||
| 		s->session->waiting_thread = AST_PTHREADT_NULL; | ||||
| @@ -4594,6 +4617,7 @@ static int do_message(struct mansession *s) | ||||
| 	struct message m = { 0 }; | ||||
| 	char header_buf[sizeof(s->session->inbuf)] = { '\0' }; | ||||
| 	int res; | ||||
| 	time_t now; | ||||
|  | ||||
| 	for (;;) { | ||||
| 		/* Check if any events are pending and do them if needed */ | ||||
| @@ -4602,6 +4626,19 @@ static int do_message(struct mansession *s) | ||||
| 		} | ||||
| 		res = get_input(s, header_buf); | ||||
| 		if (res == 0) { | ||||
| 			if (!s->session->authenticated) { | ||||
| 				if(time(&now) == -1) { | ||||
| 					ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); | ||||
| 					return -1; | ||||
| 				} | ||||
|  | ||||
| 				if (now - s->session->authstart > authtimeout) { | ||||
| 					if (displayconnects) { | ||||
| 						ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); | ||||
| 					} | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
| 			continue; | ||||
| 		} else if (res > 0) { | ||||
| 			if (ast_strlen_zero(header_buf)) { | ||||
| @@ -4635,10 +4672,18 @@ static void *session_do(void *data) | ||||
| 	struct sockaddr_in ser_remote_address_tmp; | ||||
| 	struct protoent *p; | ||||
|  | ||||
| 	if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { | ||||
| 		fclose(ser->f); | ||||
| 		ast_atomic_fetchadd_int(&unauth_sessions, -1); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| 	ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); | ||||
| 	session = build_mansession(ser_remote_address_tmp); | ||||
|  | ||||
| 	if (session == NULL) { | ||||
| 		fclose(ser->f); | ||||
| 		ast_atomic_fetchadd_int(&unauth_sessions, -1); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| @@ -4677,7 +4722,15 @@ static void *session_do(void *data) | ||||
|  | ||||
| 	AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); | ||||
|  | ||||
| 	if(time(&session->authstart) == -1) { | ||||
| 		ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); | ||||
| 		ast_atomic_fetchadd_int(&unauth_sessions, -1); | ||||
| 		ao2_unlock(session); | ||||
| 		session_destroy(session); | ||||
| 		goto done; | ||||
| 	} | ||||
| 	ao2_unlock(session); | ||||
|  | ||||
| 	astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);	/* welcome prompt */ | ||||
| 	for (;;) { | ||||
| 		if ((res = do_message(&s)) < 0 || s.write_error) { | ||||
| @@ -4690,6 +4743,7 @@ static void *session_do(void *data) | ||||
| 			ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); | ||||
| 		} | ||||
| 	} else { | ||||
| 		ast_atomic_fetchadd_int(&unauth_sessions, -1); | ||||
| 		if (displayconnects) { | ||||
| 			ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); | ||||
| 		} | ||||
| @@ -6202,6 +6256,8 @@ static int __init_manager(int reload) | ||||
| 	block_sockets = DEFAULT_BLOCKSOCKETS; | ||||
| 	timestampevents = DEFAULT_TIMESTAMPEVENTS; | ||||
| 	httptimeout = DEFAULT_HTTPTIMEOUT; | ||||
| 	authtimeout = DEFAULT_AUTHTIMEOUT; | ||||
| 	authlimit = DEFAULT_AUTHLIMIT; | ||||
|  | ||||
| 	if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { | ||||
| 		ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n"); | ||||
| @@ -6264,6 +6320,22 @@ static int __init_manager(int reload) | ||||
| 			manager_debug = ast_true(val); | ||||
| 		} else if (!strcasecmp(var->name, "httptimeout")) { | ||||
| 			newhttptimeout = atoi(val); | ||||
| 		} else if (!strcasecmp(var->name, "authtimeout")) { | ||||
| 			int timeout = atoi(var->value); | ||||
|  | ||||
| 			if (timeout < 1) { | ||||
| 				ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value); | ||||
| 			} else { | ||||
| 				authtimeout = timeout; | ||||
| 			} | ||||
| 		} else if (!strcasecmp(var->name, "authlimit")) { | ||||
| 			int limit = atoi(var->value); | ||||
|  | ||||
| 			if (limit < 1) { | ||||
| 				ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value); | ||||
| 			} else { | ||||
| 				authlimit = limit; | ||||
| 			} | ||||
| 		} else if (!strcasecmp(var->name, "channelvars")) { | ||||
| 			struct manager_channel_variable *mcv; | ||||
| 			char *remaining = ast_strdupa(val), *next; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user