#!/usr/bin/perl -w
#
##
#
# SMBPASSWD - Openradius module that verifies passwords using the Windows
# NT domain database. 
#
##
#
# Usage: smbpasswd [-d] -D NTDOMAIN PDC [BDC]
#	 smbpasswd -h
#
# -d increases verbosity on stderr and allows module to run standalone
# The PDC and BDC names must be the NetBIOS names of the machines and
# must also be resolvable using Unix gethostbyname(). You may need to
# put these names in DNS or /etc/hosts.
#
##
#
# Authors:
# Emile van Bergen, emile@evbergen.xs4all.nl
# Brian McGraw, bmcgraw@philorch.org
#
# Permission to redistribute an original or modified version of this program
# in source, intermediate or object code form is hereby granted exclusively
# under the terms of the GNU General Public License, version 2. Please see the
# file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html.
#
# History:
# 2001/11/21 - EvB - Created
# 2003/06/20 - Brian McGraw - Modified the UNIXPASSWD module to work with 
#	       Windows domain.  This script requires the Authen::Smb Perl
#	       module,  found on CPAN.
# 2003/06/25 - EvB - Modified to allow domain, PDC and BDC to be specified
#	       on the command line.
#
##


########
# USES #
########

use Getopt::Long;
use Authen::Smb;

###########
# GLOBALS #
###########

$debug = 0;
$domain = 'DOMAIN';


########
# MAIN #
########

# Get options
Getopt::Long::Configure("bundling");
GetOptions("h"  => \$usage,
	   "d+" => \$debug,
	   "D=s"  => \$domain);
if ($usage || $#ARGV < 0) { die("Usage: smbpasswd [-d] -D ntdomain pdcname [bdcname]\n       smbpasswd -h\n"); }

# Check that we're running under OpenRADIUS, interface version 1
unless ($debug ||
	$ENV{'RADIUSINTERFACEVERSION'} &&
	$ENV{'RADIUSINTERFACEVERSION'} == 1) {
	die("smbpasswd: ERROR: not running under OpenRADIUS, interface v1!\n");
}

# Set record separator to empty line and loop on input.
$/ = "\n\n";
$| = 1;			# Important - we're outputting to a pipe
my $user; my $pass;
while(<STDIN>) {

	# Parse pairs from server's request message
	chomp;
	$user = $pass = "";
	/^\s*str\s*=\s*"(.*)"\s*$/m and $user = $1;
	/^\s*User-Password\s*=\s*"(.*)"\s*$/m and $pass = $1;

	# Debugging
	$debug and print STDERR "smbpasswd[$$]: got request: $_\n" .
				"smbpasswd[$$]: user: $user, pass: $pass\n";

	# Authenticate against NT Domain
	$authResult = Authen::Smb::authen($user, $pass,
					  $ARGV[0], $ARGV[1] || '', $domain);
	if ($authResult == 0) {
	    $debug and print STDERR "smbpasswd[$$]: user: $user, successfully authenticated.\n";
	    print "int=1\n\n";
	    next;
	} 

	if ($authResult == 1) {
	    $debug and print STDERR "smbpasswd[$$]: Unable to find SMB server.\n";
	} 
	elsif ($authResult == 3) {
	    $debug and print STDERR "smbpasswd[$$]: Username/Password incorrect.\n";
	}
	else {
	    $debug and print STDERR "smbpasswd[$$]: User not authenticated, error $authResult\n";
	}

	print "int=0\n\n";
}

