smradiusd 39.1 KB
Newer Older
Nigel Kukard's avatar
Nigel Kukard committed
1
2
#!/usr/bin/perl
# Radius daemon
3
# Copyright (C) 2007-2016, AllWorldIT
Nigel Kukard's avatar
Nigel Kukard committed
4
#
Nigel Kukard's avatar
Nigel Kukard committed
5
6
7
8
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
Nigel Kukard's avatar
Nigel Kukard committed
9
#
Nigel Kukard's avatar
Nigel Kukard committed
10
11
12
13
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
Nigel Kukard's avatar
Nigel Kukard committed
14
#
Nigel Kukard's avatar
Nigel Kukard committed
15
16
17
18
19
20
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.



Nigel Kukard's avatar
Nigel Kukard committed
21
use lib('/usr/local/lib/smradius-0.0','/usr/lib/smradius-0.0',
22
	'/usr/lib64/smradius-0.0','smradius','awitpt/lib');
Nigel Kukard's avatar
Nigel Kukard committed
23

Nigel Kukard's avatar
Nigel Kukard committed
24
25
26
27
28
29
30


package smradius::daemon;


use strict;
use warnings;
Nigel Kukard's avatar
Nigel Kukard committed
31
32


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Check if we have Net::Server::PreFork installed
if (!eval {require Net::Server::PreFork; 1;}) {
	print STDERR "You're missing Net::Server::PreFork, try 'apt-get install libnet-server-perl'\n";
	exit 1;
}

# Check Config::IniFiles is instaslled
if (!eval {require Config::IniFiles; 1;}) {
	print STDERR "You're missing Config::IniFiles, try 'apt-get install libconfig-inifiles-perl'\n";
	exit 1;
}

# Check DateTime is installed
if (!eval {require DateTime; 1;}) {
	print STDERR "You're missing DateTime, try 'apt-get install libdatetime-perl'\n";
	exit 1;
}

# Check Cache::FastMmap is installed
if (!eval {require Cache::FastMmap; 1;}) {
	print STDERR "You're missing DateTime, try 'apt-get install libcache-fastmmap-perl'\n";
	exit 1;
} else {
56
	eval {use AWITPT::Cache;};
57
58
59
}


Nigel Kukard's avatar
Nigel Kukard committed
60
61
62
63
64
## no critic (BuiltinFunctions::ProhibitStringyEval)
eval qq{
	use base qw(Net::Server::PreFork);
};
## use critic
Nigel Kukard's avatar
Nigel Kukard committed
65

Nigel Kukard's avatar
Nigel Kukard committed
66
use Getopt::Long;
Nigel Kukard's avatar
Nigel Kukard committed
67
use Socket;
Nigel Kukard's avatar
Nigel Kukard committed
68
use Sys::Syslog;
Robert Anderson's avatar
   
Robert Anderson committed
69
use Time::HiRes qw( gettimeofday tv_interval );
Nigel Kukard's avatar
Nigel Kukard committed
70

Nigel Kukard's avatar
Nigel Kukard committed
71
72
73
use AWITPT::DB::DBILayer;
use Radius::Packet;

Nigel Kukard's avatar
Nigel Kukard committed
74
75
use smradius::version;
use smradius::constants;
Nigel Kukard's avatar
Nigel Kukard committed
76
use smradius::daemon::request;
Nigel Kukard's avatar
Nigel Kukard committed
77
78
use smradius::logging;
use smradius::config;
79
use smradius::util;
80
use smradius::attributes;
Nigel Kukard's avatar
Nigel Kukard committed
81
82


83

Nigel Kukard's avatar
Nigel Kukard committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


# Override configuration
sub configure {
	my ($self,$defaults) = @_;
	my $server = $self->{'server'};


	# If we hit a hash, add the config vars to the server
	if (defined($defaults)) {
		foreach my $item (keys %{$defaults}) {
			$server->{$item} = $defaults->{$item};
		}
		return;
	}

	# Set defaults
	my $cfg;
	$cfg->{'config_file'} = "/etc/smradiusd.conf";
103
	$cfg->{'cache_file'} = '/var/run/smradius/cache';
Nigel Kukard's avatar
Nigel Kukard committed
104
105
106

	$server->{'timeout'} = 120;
	$server->{'background'} = "yes";
107
	$server->{'pid_file'} = "/var/run/smradius/smradiusd.pid";
Nigel Kukard's avatar
Nigel Kukard committed
108
	$server->{'log_level'} = 2;
109
	$server->{'log_file'} = "/var/log/smradius/smradiusd.log";
Nigel Kukard's avatar
Nigel Kukard committed
110
111
112
113

	$server->{'host'} = "*";
	$server->{'port'} = [ 1812, 1813 ];
	$server->{'proto'} = 'udp';
Nigel Kukard's avatar
Nigel Kukard committed
114

Nigel Kukard's avatar
Nigel Kukard committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	$server->{'min_servers'} = 4;
	$server->{'min_spare_servers'} = 4;
	$server->{'max_spare_servers'} = 12;
	$server->{'max_servers'} = 25;
	$server->{'max_requests'} = 1000;

	# Parse command line params
	my $cmdline;
	%{$cmdline} = ();
	GetOptions(
			\%{$cmdline},
			"help",
			"config:s",
			"debug",
			"fg",
	) or die "Error parsing commandline arguments";
Nigel Kukard's avatar
Nigel Kukard committed
131

Nigel Kukard's avatar
Nigel Kukard committed
132
133
134
135
136
137
138
139
140
141
142
143
144
	# Check for some args
	if ($cmdline->{'help'}) {
		$self->displayHelp();
		exit 0;
	}
	if (defined($cmdline->{'config'}) && $cmdline->{'config'} ne "") {
		$cfg->{'config_file'} = $cmdline->{'config'};
	}

	# Check config file exists
	if (! -f $cfg->{'config_file'}) {
		die("No configuration file '".$cfg->{'config_file'}."' found!\n");
	}
Nigel Kukard's avatar
Nigel Kukard committed
145

Nigel Kukard's avatar
Nigel Kukard committed
146
147
148
149
150
151
152
	# Use config file, ignore case
	tie my %inifile, 'Config::IniFiles', (
			-file => $cfg->{'config_file'},
			-nocase => 1
	) or die "Failed to open config file '".$cfg->{'config_file'}."': $!";
	# Copy config
	my %config = %inifile;
153
	#untie(%inifile);
Nigel Kukard's avatar
Nigel Kukard committed
154
155
156
157
158
159
160

	# Pull in params for the server
	my @server_params = (
			'log_level','log_file',
#			'port',   - We don't want to override this do we?
			'host',
			'cidr_allow', 'cidr_deny',
Nigel Kukard's avatar
Nigel Kukard committed
161
			'pid_file',
Nigel Kukard's avatar
Nigel Kukard committed
162
163
164
			'user', 'group',
			'timeout',
			'background',
Nigel Kukard's avatar
Nigel Kukard committed
165
			'min_servers',
Nigel Kukard's avatar
Nigel Kukard committed
166
167
168
			'min_spare_servers',
			'max_spare_servers',
			'max_servers',
169
			'max_requests'
Nigel Kukard's avatar
Nigel Kukard committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	);
	foreach my $param (@server_params) {
		$server->{$param} = $config{'server'}{$param} if (defined($config{'server'}{$param}));
	}

	# Fix up these ...
	if (defined($server->{'cidr_allow'})) {
		my @lst = split(/,\s;/,$server->{'cidr_allow'});
		$server->{'cidr_allow'} = \@lst;
	}
	if (defined($server->{'cidr_deny'})) {
		my @lst = split(/,\s;/,$server->{'cidr_deny'});
		$server->{'cidr_deny'} = \@lst;
	}

	# Override
	if ($cmdline->{'debug'}) {
		$server->{'log_level'} = 4;
		$cfg->{'debug'} = 1;
	}

	# If we set on commandline for foreground, keep in foreground
	if ($cmdline->{'fg'} || (defined($config{'server'}{'background'}) && $config{'server'}{'background'} eq "no" )) {
		$server->{'background'} = undef;
		$server->{'log_file'} = undef;
	} else {
		$server->{'setsid'} = 1;
	}

	# Loop with logging detail
	if (defined($config{'server'}{'log_detail'})) {
		# Lets see what we have to enable
		foreach my $detail (split(/[,\s;]/,$config{'server'}{'log_detail'})) {
			$cfg->{'logging'}{$detail} = 1;
		}
	}
Nigel Kukard's avatar
Nigel Kukard committed
206

207
	#
208
	# System modules
209
	#
210
211
212
	if (ref($config{'system'}{'modules'}) eq "ARRAY") {
		foreach my $module (@{$config{'system'}{'modules'}}) {
			$module =~ s/\s+//g;
Nigel Kukard's avatar
Nigel Kukard committed
213
214
215
			# Skip comments
			next if ($module =~ /^#/);
			$module = "system/$module";
216
217
218
219
220
221
222
223
224
225
			push(@{$cfg->{'module_list'}},$module);
		}
	} else {
		my @moduleList = split(/\s+/,$config{'system'}{'modules'});
		foreach my $module (@moduleList) {
			# Skip comments
			next if ($module =~ /^#/);
			$module = "system/$module";
			push(@{$cfg->{'module_list'}},$module);
		}
226
227
	}

Nigel Kukard's avatar
Nigel Kukard committed
228
	#
229
	# Feature modules
Nigel Kukard's avatar
Nigel Kukard committed
230
	#
231
232
233
	if (ref($config{'features'}{'modules'}) eq "ARRAY") {
		foreach my $module (@{$config{'features'}{'modules'}}) {
			$module =~ s/\s+//g;
Nigel Kukard's avatar
Nigel Kukard committed
234
235
236
			# Skip comments
			next if ($module =~ /^#/);
			$module = "features/$module";
237
238
239
240
241
242
243
244
245
246
			push(@{$cfg->{'module_list'}},$module);
		}
	} else {
		my @moduleList = split(/\s+/,$config{'features'}{'modules'});
		foreach my $module (@moduleList) {
			# Skip comments
			next if ($module =~ /^#/);
			$module = "features/$module";
			push(@{$cfg->{'module_list'}},$module);
		}
247
248
	}

249
	#
250
	# Authentication modules
251
	#
252
253
254
	if (ref($config{'authentication'}{'mechanisms'}) eq "ARRAY") {
		foreach my $module (@{$config{'authentication'}{'mechanisms'}}) {
			$module =~ s/\s+//g;
Nigel Kukard's avatar
Nigel Kukard committed
255
256
257
			# Skip comments
			next if ($module =~ /^#/);
			$module = "authentication/$module";
258
259
260
261
262
263
264
265
266
267
			push(@{$cfg->{'module_list'}},$module);
		}
	} else {
		my @moduleList = split(/\s+/,$config{'authentication'}{'mechanisms'});
		foreach my $module (@moduleList) {
			# Skip comments
			next if ($module =~ /^#/);
			$module = "authentication/$module";
			push(@{$cfg->{'module_list'}},$module);
		}
268
269
	}

270
271
272
	if (ref($config{'authentication'}{'users'}) eq "ARRAY") {
		foreach my $module (@{$config{'authentication'}{'users'}}) {
			$module =~ s/\s+//g;
Nigel Kukard's avatar
Nigel Kukard committed
273
274
275
			# Skip comments
			next if ($module =~ /^#/);
			$module = "userdb/$module";
276
277
278
279
280
281
282
283
284
285
			push(@{$cfg->{'module_list'}},$module);
		}
	} else {
		my @moduleList = split(/\s+/,$config{'authentication'}{'users'});
		foreach my $module (@moduleList) {
			# Skip comments
			next if ($module =~ /^#/);
			$module = "userdb/$module";
			push(@{$cfg->{'module_list'}},$module);
		}
286
287
	}

288
	#
289
	# Accounting modules
290
	#
291
292
	if (ref($config{'accounting'}{'modules'}) eq "ARRAY") {
		foreach my $module (@{$config{'accounting'}{'modules'}}) {
293
			$module =~ s/\s+//g;
Nigel Kukard's avatar
Nigel Kukard committed
294
295
296
			# Skip comments
			next if ($module =~ /^#/);
			$module = "accounting/$module";
297
298
299
			push(@{$cfg->{'module_list'}},$module);
		}
	} else {
300
		my @moduleList = split(/\s+/,$config{'accounting'}{'modules'});
301
302
303
304
305
306
307
		foreach my $module (@moduleList) {
			# Skip comments
			next if ($module =~ /^#/);
			$module = "accounting/$module";
			push(@{$cfg->{'module_list'}},$module);
		}
	}
308

Nigel Kukard's avatar
Nigel Kukard committed
309
310
311
312
	#
	# Dictionary configuration
	#
	# Split off dictionaries to load
313
314
	if (ref($config{'dictionary'}->{'load'}) eq "ARRAY") {
		foreach my $dict (@{$config{'dictionary'}->{'load'}}) {
Nigel Kukard's avatar
Nigel Kukard committed
315
			$dict =~ s/\s+//g;
Nigel Kukard's avatar
Nigel Kukard committed
316
317
			# Skip comments
			next if ($dict =~ /^#/);
Nigel Kukard's avatar
Nigel Kukard committed
318
319
320
			push(@{$cfg->{'dictionary_list'}},$dict);
		}
	} else {
321
		my @dictList = split(/\s+/,$config{'dictionary'}->{'load'});
Nigel Kukard's avatar
Nigel Kukard committed
322
323
324
325
326
		foreach my $dict (@dictList) {
			# Skip comments
			next if ($dict =~ /^#/);
			push(@{$cfg->{'dictionary_list'}},$dict);
		}
Nigel Kukard's avatar
Nigel Kukard committed
327
	}
Nigel Kukard's avatar
Nigel Kukard committed
328

329
330
331
332
333
334
	# Check if the user specified a cache_file in the config
	if (defined($config{'server'}{'cache_file'})) {
		$cfg->{'cache_file'} = $config{'server'}{'cache_file'};
	}


Nigel Kukard's avatar
Nigel Kukard committed
335
336
337
338
	# Save our config and stuff
	$self->{'config'} = $cfg;
	$self->{'cmdline'} = $cmdline;
	$self->{'inifile'} = \%config;
Nigel Kukard's avatar
Nigel Kukard committed
339
340

	return;
Nigel Kukard's avatar
Nigel Kukard committed
341
342
343
344
345
346
347
348
349
350
}



# Run straight after ->run
sub post_configure_hook {
	my $self = shift;
	my $config = $self->{'config'};


351
352
	$self->log(LOG_NOTICE,"[SMRADIUS] SMRadius - v".VERSION);

Robert Anderson's avatar
Robert Anderson committed
353
	# Init config
Robert Anderson's avatar
   
Robert Anderson committed
354
	$self->log(LOG_INFO,"[SMRADIUS] Initializing configuration...");
Robert Anderson's avatar
Robert Anderson committed
355
	smradius::config::Init($self);
Robert Anderson's avatar
   
Robert Anderson committed
356
	$self->log(LOG_INFO,"[SMRADIUS] Configuration initialized.");
Robert Anderson's avatar
Robert Anderson committed
357

Nigel Kukard's avatar
Nigel Kukard committed
358
	# Load dictionaries
Robert Anderson's avatar
   
Robert Anderson committed
359
	$self->log(LOG_INFO,"[SMRADIUS] Initializing dictionaries...");
Nigel Kukard's avatar
Nigel Kukard committed
360
	my $dict = Radius::Dictionary->new();
Nigel Kukard's avatar
Nigel Kukard committed
361
	foreach my $df (@{$config->{'dictionary_list'}}) {
Nigel Kukard's avatar
Nigel Kukard committed
362
		# Load dictionary
Nigel Kukard's avatar
Nigel Kukard committed
363
364
		if (!$dict->readfile($df)) {
			$self->log(LOG_WARN,"[SMRADIUS] Failed to load dictionary '$df': $!");
Nigel Kukard's avatar
Nigel Kukard committed
365
		}
Nigel Kukard's avatar
Nigel Kukard committed
366
		$self->log(LOG_DEBUG,"[SMRADIUS] Loaded dictionary '$df'.");
Nigel Kukard's avatar
Nigel Kukard committed
367
	}
Robert Anderson's avatar
   
Robert Anderson committed
368
	$self->log(LOG_INFO,"[SMRADIUS] Dictionaries initialized.");
Nigel Kukard's avatar
Nigel Kukard committed
369
370
371
	# Store the dictionary
	$self->{'radius'}->{'dictionary'} = $dict;

Robert Anderson's avatar
   
Robert Anderson committed
372
	$self->log(LOG_INFO,"[SMRADIUS] Initializing modules...");
373
374
375
376
377
378
379
	# Load modules
	foreach my $module (@{$config->{'module_list'}}) {
		# Split off dir and mod name
		$module =~ /^(\w+)\/(\w+)$/;
		my ($mod_dir,$mod_name) = ($1,$2);

		# Load module
Nigel Kukard's avatar
Nigel Kukard committed
380
381
		## no critic (BuiltinFunctions::ProhibitStringyEval)
		my $res = eval qq{
382
383
			use smradius::modules::${mod_dir}::${mod_name};
			plugin_register(\$self,\"${mod_name}\",\$smradius::modules::${mod_dir}::${mod_name}::pluginInfo);
Nigel Kukard's avatar
Nigel Kukard committed
384
385
		};
		## use critic
Nigel Kukard's avatar
Nigel Kukard committed
386
		if ($@ || (defined($res) && $res != 0)) {
387
			$self->log(LOG_WARN,"[SMRADIUS] Error loading module $module ($@)");
Nigel Kukard's avatar
Nigel Kukard committed
388
		} else {
389
			$self->log(LOG_DEBUG,"[SMRADIUS] Plugin '$module' loaded.");
Nigel Kukard's avatar
Nigel Kukard committed
390
391
		}
	}
Robert Anderson's avatar
   
Robert Anderson committed
392
	$self->log(LOG_INFO,"[SMRADIUS] Plugins initialized.");
Nigel Kukard's avatar
Nigel Kukard committed
393

Robert Anderson's avatar
   
Robert Anderson committed
394
	$self->log(LOG_INFO,"[SMRADIUS] Initializing system modules.");
Nigel Kukard's avatar
Nigel Kukard committed
395
	# Init caching engine
396
	AWITPT::Cache::Init($self,{
397
398
399
400
401
		'cache_file' => $self->{'config'}{'cache_file'},
		'cache_file_user' => $self->{'server'}->{'user'},
		'cache_file_group' => $self->{'server'}->{'group'}
	});

Robert Anderson's avatar
   
Robert Anderson committed
402
	$self->log(LOG_INFO,"[SMRADIUS] System modules initialized.");
Nigel Kukard's avatar
Nigel Kukard committed
403

Nigel Kukard's avatar
Nigel Kukard committed
404
	return;
Nigel Kukard's avatar
Nigel Kukard committed
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
}



# Register plugin info
sub plugin_register {
	my ($self,$plugin,$info) = @_;


	# If no info, return
	if (!defined($info)) {
		print(STDERR "WARNING: Plugin info not found for plugin => $plugin\n");
		return -1;
	}

	# Set real module name & save
	$info->{'Module'} = $plugin;
422
	push(@{$self->{'module_list'}},$info);
Nigel Kukard's avatar
Nigel Kukard committed
423
424
425
426
427
428
429
430
431
432

	# If we should, init the module
	if (defined($info->{'Init'})) {
		$info->{'Init'}($self);
	}

	return 0;
}


433

Nigel Kukard's avatar
Nigel Kukard committed
434
435
436
437
# Initialize child
sub child_init_hook
{
	my $self = shift;
438
	my $config = $self->{'config'};
Nigel Kukard's avatar
Nigel Kukard committed
439

Nigel Kukard's avatar
Nigel Kukard committed
440

Nigel Kukard's avatar
Nigel Kukard committed
441
	$self->SUPER::child_init_hook();
Nigel Kukard's avatar
Nigel Kukard committed
442

Nigel Kukard's avatar
Nigel Kukard committed
443
	$self->log(LOG_INFO,"[SMRADIUS] Starting up caching engine");
444
	AWITPT::Cache::connect($self);
Nigel Kukard's avatar
Nigel Kukard committed
445

446
	# Do we need database support?
Robert Anderson's avatar
Robert Anderson committed
447
	if ($self->{'smradius'}->{'database'}->{'enabled'}) {
448
449
450
451
452
		# This is the database connection timestamp, if we connect, it resets to 0
		# if not its used to check if we must kill the child and try a reconnect
		$self->{'client'}->{'dbh_status'} = time();

		# Init core database support
453
		$self->{'client'}->{'dbh'} = AWITPT::DB::DBILayer::Init($self,'smradius');
454
455
456
		if (defined($self->{'client'}->{'dbh'})) {
			# Check if we succeeded
			if (!($self->{'client'}->{'dbh'}->connect())) {
Nigel Kukard's avatar
Nigel Kukard committed
457
			# If we succeeded, record OK
458
459
				$self->{'client'}->{'dbh_status'} = 0;
			} else {
Nigel Kukard's avatar
Nigel Kukard committed
460
461
				$self->log(LOG_WARN,"[SMRADIUS] Failed to connect to database: ".$self->{'client'}->{'dbh'}->Error().
						" ($$)");
462
			}
Nigel Kukard's avatar
Nigel Kukard committed
463
		} else {
464
			$self->log(LOG_WARN,"[SMRADIUS] Failed to Initialize: ".awitpt::db::dbilayer::internalError()." ($$)");
Nigel Kukard's avatar
Nigel Kukard committed
465
466
		}
	}
Nigel Kukard's avatar
Nigel Kukard committed
467

Nigel Kukard's avatar
Nigel Kukard committed
468
	return;
Nigel Kukard's avatar
Nigel Kukard committed
469
470
471
472
473
474
475
476
477
478
}



# Destroy the child
sub child_finish_hook {
	my $self = shift;
	my $server = $self->{'server'};

	$self->SUPER::child_finish_hook();
Nigel Kukard's avatar
Nigel Kukard committed
479

Nigel Kukard's avatar
Nigel Kukard committed
480
	$self->log(LOG_INFO,"[SMRADIUS] Shutting down caching engine ($$)");
481
	AWITPT::Cache::disconnect($self);
Nigel Kukard's avatar
Nigel Kukard committed
482
483

	return;
Nigel Kukard's avatar
Nigel Kukard committed
484
485
486
}


487

Nigel Kukard's avatar
Nigel Kukard committed
488
489
490
491
# Process requests we get
sub process_request {
	my $self = shift;
	my $server = $self->{'server'};
492
	my $client = $self->{'client'};
493
	my $log = defined($server->{'config'}{'logging'}{'module_list'});
Nigel Kukard's avatar
Nigel Kukard committed
494
495
496
497
498
499
500
501
502
503
504
505


	# Grab packet
	my $udp_packet = $server->{'udp_data'};

	# Check min size
	if (length($udp_packet) < 18)
	{
		$self->log(LOG_WARN, "[SMRADIUS] Packet too short - Ignoring");
		return;
	}

506
	# Very first timer ...
Robert Anderson's avatar
   
Robert Anderson committed
507
508
	my $timer0 = [gettimeofday];

509
510
511
	# Grab NOW()
	my $now = time();

Nigel Kukard's avatar
Nigel Kukard committed
512
	# Parse packet
Nigel Kukard's avatar
Nigel Kukard committed
513
	my $pkt = Radius::Packet->new($self->{'radius'}->{'dictionary'},$udp_packet);
Nigel Kukard's avatar
Nigel Kukard committed
514
515

	# VERIFY SOURCE SERVER
516
	$self->log(LOG_DEBUG,"[SMRADIUS] Packet From = > ".$server->{'peeraddr'});
Nigel Kukard's avatar
Nigel Kukard committed
517

Robert Anderson's avatar
Robert Anderson committed
518
519
520
521
522
523
524
	# Check if we got connected, if not ... bypass
	if ($self->{'client'}->{'dbh_status'} > 0) {
		my $action;

		$self->log(LOG_WARN,"[SMRADIUS] Client in BYPASS mode due to DB connection failure!");
		# Check bypass mode
		if (!defined($self->{'inifile'}{'database'}{'bypass_mode'})) {
Nigel Kukard's avatar
Nigel Kukard committed
525
526
			$self->log(LOG_ERR,
					"[SMRADIUS] No bypass_mode specified for failed database connections, defaulting to tempfail");
Robert Anderson's avatar
Robert Anderson committed
527
528
529
530
531
532
			$action = "tempfail";
		# Check for "tempfail"
		} elsif (lc($self->{'inifile'}{'database'}{'bypass_mode'}) eq "tempfail") {
		# And for "bypass"
		} elsif (lc($self->{'inifile'}{'database'}{'bypass_mode'}) eq "pass") {
		}
Nigel Kukard's avatar
Nigel Kukard committed
533

Robert Anderson's avatar
Robert Anderson committed
534
535
536
537
538
539
540
		# Check if we need to reconnect or not
		my $timeout = $self->{'inifile'}{'database'}{'bypass_timeout'};
		if (!defined($timeout)) {
			$self->log(LOG_ERR,"[SMRADIUS] No bypass_timeout specified for failed database connections, defaulting to 120s");
			$timeout = 120;
		}
		# Get time left
541
		my $timepassed = $now - $self->{'client'}->{'dbh_status'};
Robert Anderson's avatar
Robert Anderson committed
542
543
		# Then check...
		if ($timepassed >= $timeout) {
Robert Anderson's avatar
   
Robert Anderson committed
544
			$self->log(LOG_WARN,"[SMRADIUS] Client BYPASS timeout exceeded, reconnecting...");
Robert Anderson's avatar
Robert Anderson committed
545
546
			exit 0;
		} else {
Robert Anderson's avatar
   
Robert Anderson committed
547
			$self->log(LOG_WARN,"[SMRADIUS] Client still in BYPASS mode, ".( $timeout - $timepassed ).
Nigel Kukard's avatar
Nigel Kukard committed
548
					"s left till next reconnect");
Robert Anderson's avatar
Robert Anderson committed
549
550
551
552
553
			return;
		}
	}

	# Setup database handle
554
	AWITPT::DB::DBLayer::setHandle($self->{'client'}->{'dbh'});
Robert Anderson's avatar
Robert Anderson committed
555

Robert Anderson's avatar
   
Robert Anderson committed
556
	# Log line to use with logging
557
558
559
	my $logLine = "";
	my @logLineArgs;
	my $logReason = "UNKNOWN";
Robert Anderson's avatar
   
Robert Anderson committed
560
	foreach my $attr ($pkt->attributes) {
561
562
		$logLine .= " %s: '%s',";
		push(@logLineArgs,$attr,$pkt->rawattr($attr));
Robert Anderson's avatar
   
Robert Anderson committed
563
	}
564
	# Chop off ,
Robert Anderson's avatar
   
Robert Anderson committed
565
566
	chop($logLine);

567
568
	# Main user hash with everything in
	my $user;
569
	$user->{'ConfigAttributes'} = {};
570
571
	$user->{'Attributes'} = {};
	$user->{'VAttributes'} = {};
572
573
	$user->{'ReplyAttributes'} = {};
	$user->{'ReplyVAttributes'} = {};
574
	$user->{'AttributeConditionalVariables'} = {};
575

576
	# Private data
577
	# Where we going to get the timestamp to use from?, from the packet, if its there, or from ourselves
578
	if (defined($pkt->rawattr('Event-Timestamp')) && $self->{'smradius'}->{'use_packet_timestamp'}) {
579
580
		$user->{'_Internal'}->{'Timestamp-Unix'} = $pkt->rawattr('Event-Timestamp');
	} else {
581
		$user->{'_Internal'}->{'Timestamp-Unix'} = $now;
582
583
	}

584
585
586
587
	# VERY IMPORTANT!!!!!!
	# Timestamp AND Timestamp-Unix are in the CONVERTED timezone (event_timezone)
	my $eventTimestamp = DateTime->from_epoch(
			epoch => $user->{'_Internal'}->{'Timestamp-Unix'},
Nigel Kukard's avatar
Nigel Kukard committed
588
			time_zone => $self->{'smradius'}->{'event_timezone'}
589
	);
590
591
	$user->{'_Internal'}->{'Timestamp'} = $eventTimestamp->strftime('%Y-%m-%d %H:%M:%S');

592
593
	# Set username
	$user->{'Username'} = $pkt->attr('User-Name');
594

595
596
597
598
599
600
	# Username should always be defined?
	if (!defined($user->{'Username'})) {
		$self->log(LOG_NOTICE,"[SMRADIUS] Packet with no username from ".$server->{'peeraddr'});
		return;
	}

601
602
603
604
605
	# First thing we do is to make sure the NAS behaves if we using abuse prevention
	if ($self->{'smradius'}->{'use_abuse_prevention'} && defined($user->{'Username'})) {
		my ($res,$val) = cacheGetKeyPair('FloodCheck',$server->{'peeraddr'}."/".$user->{'Username'}."/".$pkt->code);
		if (defined($val)) {
			my $timePeriod = $now - $val;
Nigel Kukard's avatar
Nigel Kukard committed
606
			if ($pkt->code eq "Access-Request" && $timePeriod < $self->{'smradius'}->{'access_request_abuse_threshold'}) {
Nigel Kukard's avatar
Nigel Kukard committed
607
				$self->log(LOG_NOTICE,"[SMRADIUS] ABUSE: Server trying too fast. server = ".$server->{'peeraddr'}.", user = ".$user->{'Username'}.
608
609
610
						", code = ".$pkt->code.", timeout = ".($now - $val));
				return;
			} elsif ($pkt->code eq "Accounting-Request" && $timePeriod < $self->{'smradius'}->{'accounting_request_abuse_threshold'}) {
Nigel Kukard's avatar
Nigel Kukard committed
611
				$self->log(LOG_NOTICE,"[SMRADIUS] ABUSE: Server trying too fast. server = ".$server->{'peeraddr'}.", user = ".$user->{'Username'}.
612
613
614
615
616
617
618
619
						", code = ".$pkt->code.", timeout = ".($now - $val));
				return;
			}
		}
		# We give the benefit of the doubt and let a query take 60s. We update to right stamp at end of this function
		cacheStoreKeyPair('FloodCheck',$server->{'peeraddr'}."/".$user->{'Username'}."/".$pkt->code,$now + 60);
	}

620
	#
Nigel Kukard's avatar
Nigel Kukard committed
621
	# GRAB & PROCESS CONFIG
622
	#
623

624
	foreach my $module (@{$self->{'module_list'}}) {
625
626
627
628
		# Try find config attribute
		if ($module->{'Config_get'}) {

			# Get result from config module
Nigel Kukard's avatar
Nigel Kukard committed
629
			$self->log(LOG_DEBUG,"[SMRADIUS] CONFIG: Trying plugin '".$module->{'Name'}."' for incoming connection");
630
631
632
633
			my $res = $module->{'Config_get'}($self,$user,$pkt);

			# Check result
			if (!defined($res)) {
Robert Anderson's avatar
   
Robert Anderson committed
634
635
				$self->log(LOG_WARN,"[SMRADIUS] CONFIG: Error with plugin '".$module->{'Name'}."'");
				$logReason = "Config Error";
636
637
638
639
640
641
642

			# Check if we skipping this plugin
			} elsif ($res == MOD_RES_SKIP) {
				$self->log(LOG_DEBUG,"[SMRADIUS] CONFIG: Skipping '".$module->{'Name'}."'");

			# Check if we got a positive result back
			} elsif ($res == MOD_RES_ACK) {
Nigel Kukard's avatar
Nigel Kukard committed
643
				$self->log(LOG_DEBUG,"[SMRADIUS] CONFIG: Configuration retrieved from '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
644
				$logReason = "Config Retrieved";
645
646
647

			# Check if we got a negative result back
			} elsif ($res == MOD_RES_NACK) {
Nigel Kukard's avatar
Nigel Kukard committed
648
				$self->log(LOG_DEBUG,"[SMRADIUS] CONFIG: Configuration rejection when using '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
649
				$logReason = "Config Rejected";
650
				goto CHECK_RESULT;
651
652
653
654
			}
		}
	}

655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
	# If we have a config attribute to transform username, use it
	if (defined($user->{'ConfigAttributes'}->{'SMRadius-Username-Transform'})) {

		$self->log(LOG_DEBUG,"[SMRADIUS] Attribute 'SMRadius-Username-Transform' exists, transforming username.");

# NK: Not ready for prime time yet
#		# Get clients(NAS) username transform pattern
#		my $transform = shift(@{$user->{'ConfigAttributes'}->{'SMRadius-Username-Transform'}});
#		if ($transform =~ /^(@\S+)=(@\S+)$/i) {
#
#			# Set old and new, prevents warnings
#			my ($old,$new) = ($1,$2);
#
#			# Use client username transform on temp username
#			my $tempUsername = $user->{'Username'};
#			$tempUsername =~ s/$old/$new/;
#
#			# Override username
#			$user->{'Username'} = $tempUsername;
#		} else {
#			$self->log(LOG_DEBUG,"[SMRADIUS] No string replacement possible on pattern '".
#					$transform."', using username '".$user->{'Username'}."'");
#		}
	}

680
681
682
	# Get the user timer
	my $timer1 = [gettimeofday];

683
684
	# FIXME - need secret
	# FIXME - need acl list
685

686
	#
687
	# START PROCESSING
688
689
	#

690
691
	# Common stuff for multiple codes....
	if ($pkt->code eq "Accounting-Request" || $pkt->code eq "Access-Request") {
Nigel Kukard's avatar
Nigel Kukard committed
692

693
694
695
696
697
		#
		# FIND USER
		#

		# Loop with modules to try find user
698
		foreach my $module (@{$self->{'module_list'}}) {
699
700
			# Try find user
			if ($module->{'User_find'}) {
Nigel Kukard's avatar
Nigel Kukard committed
701
				$self->log(LOG_DEBUG,"[SMRADIUS] FIND: Trying plugin '".$module->{'Name'}."' for username '".
702
						$user->{'Username'}."'");
703
				my ($res,$userdb_data) = $module->{'User_find'}($self,$user,$pkt);
704
705
706

				# Check result
				if (!defined($res)) {
Robert Anderson's avatar
   
Robert Anderson committed
707
708
					$self->log(LOG_WARN,"[SMRADIUS] FIND: Error with plugin '".$module->{'Name'}."'");
					$logReason = "Error Finding User";
709
710
711
712
713
714
715

				# Check if we skipping this plugin
				} elsif ($res == MOD_RES_SKIP) {
					$self->log(LOG_DEBUG,"[SMRADIUS] FIND: Skipping '".$module->{'Name'}."'");

				# Check if we got a positive result back
				} elsif ($res == MOD_RES_ACK) {
Nigel Kukard's avatar
Nigel Kukard committed
716
					$self->log(LOG_DEBUG,"[SMRADIUS] FIND: Username found with '".$module->{'Name'}."'");
717
					$user->{'_UserDB'} = $module;
718
					$user->{'_UserDB_Data'} = $userdb_data;
719
720
721
722
					last;

				# Or a negative result
				} elsif ($res == MOD_RES_NACK) {
Nigel Kukard's avatar
Nigel Kukard committed
723
					$self->log(LOG_DEBUG,"[SMRADIUS] FIND: Username not found with '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
724
					$logReason = "User Not Found";
725
726
727
728
729
730
731
					last;

				}
			}
		}
	}

732
733
734
	# Process the packet timer
	my $timer2 = [gettimeofday];

735

Nigel Kukard's avatar
Nigel Kukard committed
736
737
738
	# Is this an accounting request
	if ($pkt->code eq "Accounting-Request") {

739
		$self->log(LOG_DEBUG,"[SMRADIUS] Accounting Request Packet");
Nigel Kukard's avatar
Nigel Kukard committed
740

741
742
743
744
745
		#
		# GET USER
		#

		# Get user data
746
747
		if (defined($user->{'_UserDB'}) && defined($user->{'_UserDB'}->{'User_get'})) {
			my $res = $user->{'_UserDB'}->{'User_get'}($self,$user,$pkt);
748
749

			# Check result
750
751
752
			if ($res) {
				$self->log(LOG_WARN,"[SMRADIUS] GET: Error returned from '".$user->{'_UserDB'}->{'Name'}.
						"' for username '".$user->{'Username'}."'");
753
754
755
			}
		}

756
		# Loop with modules to try something that handles accounting
757
		foreach my $module (@{$self->{'module_list'}}) {
758
759
			# Try find user
			if ($module->{'Accounting_log'}) {
Nigel Kukard's avatar
Nigel Kukard committed
760
				$self->log(LOG_DEBUG,"[SMRADIUS] ACCT: Trying plugin '".$module->{'Name'}."'");
761
				my $res = $module->{'Accounting_log'}($self,$user,$pkt);
762
763
764

				# Check result
				if (!defined($res)) {
Robert Anderson's avatar
   
Robert Anderson committed
765
766
					$self->log(LOG_WARN,"[SMRADIUS] ACCT: Error with plugin '".$module->{'Name'}."'");
					$logReason = "Accounting Log Error";
767
768
769

				# Check if we skipping this plugin
				} elsif ($res == MOD_RES_SKIP) {
770
					$self->log(LOG_DEBUG,"[SMRADIUS] ACCT: Skipping '".$module->{'Name'}."'");
771
772
773

				# Check if we got a positive result back
				} elsif ($res == MOD_RES_ACK) {
Nigel Kukard's avatar
Nigel Kukard committed
774
					$self->log(LOG_DEBUG,"[SMRADIUS] ACCT: Accounting logged using '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
775
					$logReason = "Accounting Logged";
776
777
778

				# Check if we got a negative result back
				} elsif ($res == MOD_RES_NACK) {
Nigel Kukard's avatar
Nigel Kukard committed
779
					$self->log(LOG_DEBUG,"[SMRADIUS] ACCT: Accounting NOT LOGGED using '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
780
					$logReason = "Accounting NOT Logged";
781
782
783
				}
			}
		}
784

Nigel Kukard's avatar
Nigel Kukard committed
785
		# Tell the NAS we got its packet
786
		my $resp = Radius::Packet->new($self->{'radius'}->{'dictionary'});
Robert Anderson's avatar
Robert Anderson committed
787
		$resp->set_code('Accounting-Response');
788
789
		$resp->set_identifier($pkt->identifier);
		$resp->set_authenticator($pkt->authenticator);
790
		$udp_packet = auth_resp($resp->pack, getAttributeValue($user->{'ConfigAttributes'},"SMRadius-Config-Secret"));
791
		$server->{'client'}->send($udp_packet);
792

Nigel Kukard's avatar
Nigel Kukard committed
793
794
795
		# Are we going to POD the user?
		my $PODUser = 0;

Robert Anderson's avatar
Robert Anderson committed
796
		# Loop with modules that have post-accounting hooks
797
		foreach my $module (@{$self->{'module_list'}}) {
798
799
			# Try authenticate
			if ($module->{'Feature_Post-Accounting_hook'}) {
Nigel Kukard's avatar
Nigel Kukard committed
800
				$self->log(LOG_DEBUG,"[SMRADIUS] POST-ACCT: Trying plugin '".$module->{'Name'}."' for '".
801
						$user->{'Username'}."'");
802
803
804
805
				my $res = $module->{'Feature_Post-Accounting_hook'}($self,$user,$pkt);

				# Check result
				if (!defined($res)) {
Robert Anderson's avatar
   
Robert Anderson committed
806
807
					$self->log(LOG_WARN,"[SMRADIUS] POST-ACCT: Error with plugin '".$module->{'Name'}."'");
					$logReason = "Post Accounting Error";
808
809
810
811
812
813
814

				# Check if we skipping this plugin
				} elsif ($res == MOD_RES_SKIP) {
					$self->log(LOG_DEBUG,"[SMRADIUS] POST-ACCT: Skipping '".$module->{'Name'}."'");

				# Check if we got a positive result back
				} elsif ($res == MOD_RES_ACK) {
Nigel Kukard's avatar
Nigel Kukard committed
815
					$self->log(LOG_DEBUG,"[SMRADIUS] POST-ACCT: Passed post accounting hook by '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
816
					$logReason = "Post Accounting Success";
817
818
819

				# Or a negative result
				} elsif ($res == MOD_RES_NACK) {
Nigel Kukard's avatar
Nigel Kukard committed
820
					$self->log(LOG_DEBUG,"[SMRADIUS] POST-ACCT: Failed post accounting hook by '".$module->{'Name'}."'");
Robert Anderson's avatar
   
Robert Anderson committed
821
					$logReason = "Failed Post Accounting";
Nigel Kukard's avatar
Nigel Kukard committed
822
					$PODUser = 1;
823
824
825
826
				}
			}
		}

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
		# Build a list of our attributes in the packet
		my $acctAttributes;
		foreach my $attr ($pkt->attributes) {
			$acctAttributes->{$attr} = $pkt->rawattr($attr);
		}
		# Loop with attributes we got from the user
		foreach my $attrName (keys %{$user->{'Attributes'}}) {
			# Loop with operators
			foreach my $attrOp (keys %{$user->{'Attributes'}->{$attrName}}) {
				# Grab attribute
				my $attr = $user->{'Attributes'}->{$attrName}->{$attrOp};
				# Check attribute against accounting attributes attributes
				my $res = checkAcctAttribute($self,$user,$acctAttributes,$attr);
				# We don't care if it fails
			}
		}

Nigel Kukard's avatar
Nigel Kukard committed
844
845
846
		# Check if we must POD the user
		if ($PODUser) {
			$self->log(LOG_DEBUG,"[SMRADIUS] POST-ACCT: Trying to disconnect user...");
847

Nigel Kukard's avatar
Nigel Kukard committed
848
			my $resp = Radius::Packet->new($self->{'radius'}->{'dictionary'});
849

Robert Anderson's avatar
Robert Anderson committed
850
			$resp->set_code('Disconnect-Request');
Nigel Kukard's avatar
Nigel Kukard committed
851
852
			my $id = $$ & 0xff;
			$resp->set_identifier( $id );
853

Nigel Kukard's avatar
Nigel Kukard committed
854
855
856
			$resp->set_attr('User-Name',$pkt->attr('User-Name'));
			$resp->set_attr('Framed-IP-Address',$pkt->attr('Framed-IP-Address'));
			$resp->set_attr('NAS-IP-Address',$pkt->attr('NAS-IP-Address'));
857

Robert Anderson's avatar
   
Robert Anderson committed
858
859
860
			# Add onto logline
			$logLine .= ". REPLY => ";
			foreach my $attr ($resp->attributes) {
861
862
				$logLine .= " %s: '%s',";
				push(@logLineArgs,$attr,$resp->rawattr($attr));
Robert Anderson's avatar
   
Robert Anderson committed
863
			}
864
			# Chop off ,
Robert Anderson's avatar
   
Robert Anderson committed
865
866
867
			chop($logLine);

			# Grab packet
Nigel Kukard's avatar
Nigel Kukard committed
868
			$udp_packet = auth_resp($resp->pack, getAttributeValue($user->{'ConfigAttributes'},"SMRadius-Config-Secret"));
869

870
871
872
873
874
875
			# Check for POD Servers and send disconnect
			if (defined($user->{'ConfigAttributes'}->{'SMRadius-Config-PODServer'})) {
				$self->log(LOG_DEBUG,"[SMRADIUS] SMRadius-Config-PODServer is defined");

				# Check address format
				foreach my $podServerAttribute (@{$user->{'ConfigAttributes'}->{'SMRadius-Config-PODServer'}}) {
876
877
					# Check for valid IP
					if ($podServerAttribute =~ /^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/) {
878
						my $podServer = $1;
879
880
881
882
883
884
885
886

						# If we have a port, use it, otherwise use default 1700
						my $podServerPort;
						if ($podServerAttribute =~ /:([0-9]+)$/) {
							$podServerPort = $1;
						} else {
							$podServerPort = 1700;
						}
887

Robert Anderson's avatar
Robert Anderson committed
888
889
						$self->log(LOG_DEBUG,"[SMRADIUS] POST-ACCT: Trying PODServer => IP: '".$podServer."' Port: '".$podServerPort."'");

890
891
						# Create socket to send packet out on
						my $podServerTimeout = "10";  # 10 second timeout
Nigel Kukard's avatar
Nigel Kukard committed
892
						my $podSock = IO::Socket::INET->new(
893
894
895
896
897
								PeerAddr => $podServer,
								PeerPort => $podServerPort,
								Type => SOCK_DGRAM,
								Proto => 'udp',
								TimeOut => $podServerTimeout,
Robert Anderson's avatar
Robert Anderson committed
898
899
900
901
902
903
						);

						if (!$podSock) {
							$self->log(LOG_ERR,"[SMRADIUS] POST-ACCT: Failed to create socket to send POD on");
							next;
						}
904
905
906

						# Check if we sent the packet...
						if (!$podSock->send($udp_packet)) {
Robert Anderson's avatar
Robert Anderson committed
907
908
							$self->log(LOG_ERR,"[SMRADIUS] POST-ACCT: Failed to send data on socket");
							next;
909
910
911
						}

						# Once sent, we need to get a response back
Nigel Kukard's avatar
Nigel Kukard committed
912
						my $sh = IO::Select->new($podSock);
Robert Anderson's avatar
Robert Anderson committed
913
914
915
916
						if (!$sh) {
							$self->log(LOG_ERR,"[SMRADIUS] POST-ACCT: Failed to select data on socket");
							next;
						}
917

Robert Anderson's avatar
Robert Anderson committed
918
919
920
921
						if (!$sh->can_read($podServerTimeout)) {
							$self->log(LOG_ERR,"[SMRADIUS] POST-ACCT: Failed to receive data on socket");
							next;
						}
922
923

						my $data;
Robert Anderson's avatar
Robert Anderson committed
924
925
926
						$podSock->recv($data, 65536);
						if (!$data) {
							$self->log(LOG_ERR,"[SMRADIUS] POST-ACCT: Receive data failed");
Robert Anderson's avatar
   
Robert Anderson committed
927
928
929
							$logReason = "POD Failure";
						} else {
							$logReason = "User POD";
Robert Anderson's avatar
Robert Anderson committed
930
931
						}

932
933
934
935
936
937
938
939
						#my @stuff = unpack('C C n a16 a*', $data);
						#$self->log(LOG_DEBUG,"STUFF: ".Dumper(\@stuff));
					} else {
						$self->log(LOG_DEBUG,"[SMRADIUS] Invalid POD Server value: '".$podServerAttribute."'");
					}
				}
			} else {
				$self->log(LOG_DEBUG,"[SMRADIUS] SMRadius-Config-PODServer is not defined");
Nigel Kukard's avatar
Nigel Kukard committed
940
941
			}
		}
942

Nigel Kukard's avatar
Nigel Kukard committed
943
944
	# Or maybe a access request
	} elsif ($pkt->code eq "Access-Request") {
Nigel Kukard's avatar
Nigel Kukard committed
945
946


947
		$self->log(LOG_DEBUG,"[SMRADIUS] Access Request Packet");
Nigel Kukard's avatar
Nigel Kukard committed
948

949
		# Authentication variables
Nigel Kukard's avatar
Nigel Kukard committed
950
951
		my $authenticated = 0;
		my $mechanism;
952
		# Authorization variables
953
		my $authorized = 1;
Nigel Kukard's avatar
Nigel Kukard committed
954
955
956


		# If no user is found, bork out ...
957
		if (!defined($user->{'_UserDB'})) {
Nigel Kukard's avatar
Nigel Kukard committed
958
			$self->log(LOG_DEBUG,"[SMRADIUS] FIND: No plugin found for username '".$user->{'Username'}."'");
Nigel Kukard's avatar
Nigel Kukard committed
959
960
961
962
963
964
965
966
			goto CHECK_RESULT;
		}

		#
		# GET USER
		#

		# Get user data
967
968
		if ($user->{'_UserDB'}->{'User_get'}) {
			my $res = $user->{'_UserDB'}->{'User_get'}($self,$user,$pkt);
Nigel Kukard's avatar
Nigel Kukard committed
969
970

			# Check result
971
972
			if ($res) {
				$self->log(LOG_WARN,"[SMRADIUS] GET: Error returned from '".$user->{'_UserDB'}->{'Name'}.
Nigel Kukard's avatar
Nigel Kukard committed
973
						"' for username '".$user->{'Username'}."'");
Nigel Kukard's avatar
Nigel Kukard committed
974
975
				goto CHECK_RESULT;
			}
976
		} else {
977
			$self->log(LOG_ERR,"[SMRADIUS] GET: No 'User_get' function available for module '".$user->{'_UserDB'}->{'Name'}."'");
978
979

			goto CHECK_RESULT;
Nigel Kukard's avatar
Nigel Kukard committed
980
981
982
983
984
		}

		#
		# AUTHENTICATE USER
		#
Nigel Kukard's avatar
Nigel Kukard committed
985

986
		# Loop with authentication modules
987
		foreach my $module (@{$self->{'module_list'}}) {
Nigel Kukard's avatar
Nigel Kukard committed
988
			# Try authenticate
989
			if ($module->{'Authentication_try'}) {
Nigel Kukard's avatar
Nigel Kukard committed
990
				$self->log(LOG_DEBUG,"[SMRADIUS] AUTH: Trying plugin '".$module->{'Name'}."' for '".$user->{'Username'}."'");
991
				my $res = $module->{'Authentication_try'}($self,$user,$pkt);
Nigel Kukard's avatar
Nigel Kukard committed
992
993
994

				# Check result
				if (!defined($res)) {
Robert Anderson's avatar
   
Robert Anderson committed
995
					$self->log(LOG_ERR,"[SMRADIUS] AUTH: Error with plugin '".$module->{'Name'}."'");
Nigel Kukard's avatar
Nigel Kukard committed
996
997
998

				# Check if we skipping this plugin
				} elsif ($res == MOD_RES_SKIP) {
Nigel Kukard's avatar
Nigel Kukard committed
999
					$self->log(LOG_DEBUG,"[SMRADIUS] AUTH: Skipping '".$module->{'Name'}."'");
Nigel Kukard's avatar
Nigel Kukard committed
1000

For faster browsing, not all history is shown. View entire blame