[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Conversion from users/members to central db



Greetings folks,

Two commits I made (one last night and one today) have changed the
central db stuff slightly. I'm posting this here, because the SF
commits mailing list seems to be borked and only ChrisT's commits are
making it to the list (I've put in a support request to SF, and there
seem to be a lot of people having the same problem). I'm also
attaching the result from svn diff -r519:520.

So, the commit I did last night (r 520) does a number of things:

- it creates a Session::password_check function that will verify
credentials. From now on username and password verification will be
done through here. This will allow us to easily support LDAP or other
methods of authentication  fairly easily.

- Session::password_check also handles the conversion of the crypted
password into an md5 password upon first login. This means that if
you've already created your central db, you need to either re-create
(using the Pg-central.sql file) or you need to do the following:

ALTER TABLE users_conf DROP COLUMN dbconnect;
ALTER TABLE users_conf ADD COLUMN crypted_password text;

- the dbconnect variable is being ignored/dropped. Instead it will be
built on the fly since the components of it are being stored in the db
(no sense in storing the same data twice).

Today's commit was the addition of the import_member.pl script.

This script reads users/members and fetches and imports the data into
the central DB. It will die unceremoniously if it hits a user with
bad/bogus database config. The solution for that is to either remove
the user or set the right db config in the members file. Also, this
script will die with an error message if it finds a user named
'admin'. In LegerSMB 1.2, this user is reserved for central
administration (running admin.pl). The fix for that is to edit the
members file and rename the user 'admin' to something else.

Both of these things are documented in the comments of the script.

Last thing on my list is to finish admin.pl. I'm now convinced that
this script needs a completel re-write for 1.3, and I'll take that on.
It is a horrible piece of software that does really brain-dead things
and throws all ideas of usability out the window. For 1.2, I'm simply
going to graft on the central db logic to the current system and take
a couple extra showers. I'll keep saying to myself 'This is only
temporary... this is only temporary'.

Cheers,

Chris
Index: LedgerSMB/Session/DB.pm
===================================================================
--- LedgerSMB/Session/DB.pm	(revision 519)
+++ LedgerSMB/Session/DB.pm	(revision 520)
@@ -23,6 +23,9 @@
 # create - creates a new session, writes cookie upon success
 #
 # destroy - destroys session
+#
+# password_check - compares the password with the stored cryted password 
+#                  (ver. < 1.2) and the md5 one (ver. >= 1.2)
 #====================================================================
 package Session;
 
@@ -112,8 +115,8 @@
 
 	$deleteExisting->execute($login, "$myconfig{timeout} seconds") || $form->dberror(__FILE__.':'.__LINE__.': Delete from session: ');
 
-	#doing the md5 and random stuff in the db so that LedgerSMB won't
-	#require new perl modules (Digest::MD5 and a good random generator)
+	#doing the random stuff in the db so that LedgerSMB won't
+	#require a good random generator - maybe this should be reviewed, pgsql's isn't great either
 	$fetchSequence->execute() || $form->dberror(__FILE__.':'.__LINE__.': Fetch sequence id: ');
 	my ($newSessionID, $newToken) = $fetchSequence->fetchrow_array;
 
@@ -134,11 +137,6 @@
 
 sub session_destroy {
 
-	# Under the current architecture, this function is a bit problematic
-	# %myconfig is often not defined when this function needs to be called.
-	# which means that the db connection parameters are not available.
-	# moving user prefs and the session table into a central db will solve this issue
-
 	my ($form) = @_;
 
 	my $login = $form->{login};
@@ -155,4 +153,58 @@
 
 }
 
+sub password_check {
+
+	use Digest::MD5;
+
+	my ($form, $username, $password) = @_;
+
+	# use the central database handle
+	my $dbh = ${LedgerSMB::Sysconfig::GLOBALDBH};
+
+	my $fetchPassword = $dbh->prepare("SELECT uc.password, uc.crypted_password
+										 FROM users as u, users_conf as uc
+										WHERE u.username = ?
+										  AND u.id = uc.id;");
+
+	$fetchPassword->execute($username) || $form->dberror(__FILE__.':'.__LINE__.': Fetching password : ');
+
+	my ($md5Password, $cryptPassword) = $fetchPassword->fetchrow_array;
+
+	if ($cryptPassword){
+		#First time login from old system, check crypted password
+
+		if ((crypt $password, substr($username, 0, 2)) eq $cryptPassword) {	
+
+			#password was good, convert to md5 password and null crypted
+			my $updatePassword = $dbh->prepare("UPDATE users_conf
+												   SET password = md5(?),
+													   crypted_password = null
+												  FROM users
+												 WHERE users_conf.id = users.id
+												   AND users.username = ?;");
+
+			$updatePassword->execute($password, $username) || $form->dberror(__FILE__.':'.__LINE__.': Converting password : ');
+
+			return 1;
+
+		} else {
+			return 0; #password failed
+		}
+
+	}elsif ($md5Password){
+
+		if ($md5Password ne (Digest::MD5::md5_hex $password) ) {
+			return 0;
+		}
+		else{
+			return 1;
+		}
+	
+	} else {
+		#both the md5Password and cryptPasswords were blank
+		return 0;
+	}
+}
+
 1;
Index: LedgerSMB/User.pm
===================================================================
--- LedgerSMB/User.pm	(revision 519)
+++ LedgerSMB/User.pm	(revision 520)
@@ -33,6 +33,7 @@
 
 package LedgerSMB::User;
 use LedgerSMB::Sysconfig;
+use LedgerSMB::Session;
 use Data::Dumper; 
 
 sub new {
@@ -48,12 +49,12 @@
 		# for now, this is querying the table directly... ugly 
 		my $fetchUserPrefs = $dbh->prepare("SELECT acs, address, businessnumber,
 												   company, countrycode, currency,
-												   dateformat, dbconnect, dbdriver,
-												   dbhost, dbname, dboptions, dbpasswd,
-												   dbport, dbuser, email, fax, menuwidth,
-												   name, numberformat, password, print,
-												   printer, role, sid, signature, stylesheet,
-												   tel, templates, timeout, vclimit, u.username
+												   dateformat, dbdriver, dbhost, dbname, 
+												   dboptions, dbpasswd, dbport, dbuser, 
+												   email, fax, menuwidth, name, numberformat, 
+												   password, print, printer, role, sid, 
+												   signature, stylesheet, tel, templates, 
+												   timeout, vclimit, u.username
 											  FROM users_conf as uc, users as u
 											 WHERE u.username =  ?
 											   AND u.id = uc.id;");
@@ -66,6 +67,16 @@
 			$self->{$key} = $value;
 		}
 
+		chomp($self->{dbport});
+		chomp($self->{dbname});
+		chomp($self->{dbhost});
+
+		if(! int($self->{dbport})){#in case there's a space or junk in the dbport
+			$self->{dbport} = '5432';
+		}
+
+		$self->{dbconnect} = 'dbi:Pg:dbname='.$self->{dbname}.';host='.$self->{dbhost}.';port='.$self->{dbport};
+
 		if($self->{username}){
 			$self->{login} = $login;
 		}
@@ -113,12 +124,12 @@
 		# for now, this is querying the table directly... ugly 
 		my $fetchUserPrefs = $dbh->prepare("SELECT acs, address, businessnumber,
 												   company, countrycode, currency,
-												   dateformat, dbconnect, dbdriver,
-												   dbhost, dbname, dboptions, dbpasswd,
-												   dbport, dbuser, email, fax, menuwidth,
-												   name, numberformat, password, print,
-												   printer, role, sid, signature, stylesheet,
-												   tel, templates, timeout, vclimit
+												   dateformat, dbdriver, dbhost, dbname, 
+												   dboptions, dbpasswd, dbport, dbuser, 
+												   email, fax, menuwidth, name, numberformat, 
+												   password, print, printer, role, sid, 
+												   signature, stylesheet, tel, templates, 
+												   timeout, vclimit, u.username
 											  FROM users_conf as uc, users as u
 											 WHERE u.username =  ?
 											   AND u.id = uc.id;");
@@ -130,20 +141,25 @@
 		while ( my ($key, $value) = each(%{$userHashRef}) ) {
 			$myconfig{$key} = $value;
 		}
+
+		if(! int($myconfig{'dbport'})){#in case there's a space or junk in the dbport
+			$myconfig{'dbport'} = '5432';
+		}
+
+		$myconfig{'dbconnect'} = 'dbi:Pg:dbname='.$myconfig{'dbname'}.';host='.$myconfig{'dbhost'}.';port='.$myconfig{'dbport'};
 	}
  
 	return \%myconfig;
 }
 
 sub login {
-	use Digest::MD5;
 
 	my ($self, $form) = @_;
 
 	my $rc = -1;
   
 	if ($self->{login} ne "") {
-		if ($self->{password} ne (Digest::MD5::md5_hex $form->{password}) ) {
+		if (! Session::password_check($form, $form->{login}, $form->{password})) {
 			return -1;
 		}
 
@@ -719,7 +735,7 @@
 		my $userConfUpdate = $dbh->prepare("UPDATE users_conf
 											   SET acs = ?, address = ?, businessnumber = ?,
 												   company = ?, countrycode = ?, currency = ?,
-												   dateformat = ?, dbconnect = ?, dbdriver = ?,
+												   dateformat = ?, dbdriver = ?,
 												   dbhost = ?, dbname = ?, dboptions = ?, 
 												   dbpasswd = ?, dbport = ?, dbuser = ?,
 												   email = ?, fax = ?, menuwidth = ?,
@@ -732,7 +748,7 @@
 
 		$userConfUpdate->execute($self->{acs}, $self->{address}, $self->{businessnumber},
 								 $self->{company}, $self->{countrycode}, $self->{currency},
-								 $self->{dateformat}, $self->{dbconnect}, $self->{dbdriver},
+								 $self->{dateformat}, $self->{dbdriver},
 								 $self->{dbhost}, $self->{dbname}, $self->{dboptions}, 
 								 $self->{dbpasswd}, $self->{dbport}, $self->{dbuser}, 
 								 $self->{email}, $self->{fax}, $self->{menuwidth},
@@ -748,7 +764,7 @@
 
 		my $userConfInsert = $dbh->prepare("INSERT INTO users_conf(acs, address, businessnumber,
 																   company, countrycode, currency,
-																   dateformat, dbconnect, dbdriver,
+																   dateformat, dbdriver,
 																   dbhost, dbname, dboptions, dbpasswd,
 																   dbport, dbuser, email, fax, menuwidth,
 																   name, numberformat, print, printer, role, 
@@ -756,11 +772,11 @@
 																   timeout, vclimit, id, password)
 											VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
 												   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
-												   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, md5(?));");
+												   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, md5(?));");
 
 		$userConfInsert->execute($self->{acs}, $self->{address}, $self->{businessnumber},
 								 $self->{company}, $self->{countrycode}, $self->{currency},
-								 $self->{dateformat}, $self->{dbconnect}, $self->{dbdriver},
+								 $self->{dateformat}, $self->{dbdriver},
 								 $self->{dbhost}, $self->{dbname}, $self->{dboptions}, 
 								 $self->{dbpasswd}, $self->{dbport}, $self->{dbuser}, 
 								 $self->{email}, $self->{fax}, $self->{menuwidth},
Index: LedgerSMB/Form.pm
===================================================================
--- LedgerSMB/Form.pm	(revision 519)
+++ LedgerSMB/Form.pm	(revision 520)
@@ -272,8 +272,6 @@
 
 		$self->{titlebar} = ($self->{title}) ? "$self->{title} - $self->{titlebar}" : $self->{titlebar};
 
-		$self->set_cookie($init);
-
 		print qq|Content-Type: text/html\n\n
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 		"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
@@ -295,28 +293,6 @@
 	$self->{header} = 1;
 }
 
-
-sub set_cookie {
-
-	my ($self, $init) = @_;
-
-	$self->{timeout} = ($self->{timeout} > 0) ? $self->{timeout} : 3600;
-	my $t = ($self->{endsession}) ? time : time + $self->{timeout};
-
-	if ($ENV{HTTP_USER_AGENT}) {
-
-		my @d = split / +/, scalar gmtime($t);
-		my $today = "$d[0], $d[2]-$d[1]-$d[4] $d[3] GMT";
-
-		if ($init) {
-			$self->{sessionid} = time;
-		}
-
-		print qq|Set-Cookie: LedgerSMB-$self->{login}=$self->{sessionid}; expires=$today; path=/;\n| if $self->{login};
-	}
-}
-
-
 sub redirect {
 
 	my ($self, $msg) = @_;
Index: bin/login.pl
===================================================================
--- bin/login.pl	(revision 519)
+++ bin/login.pl	(revision 520)
@@ -337,6 +337,7 @@
 		}
 	}
 
+	Session::session_create($form);
 	$form->redirect;
 
 }
Index: sql/Pg-central.sql
===================================================================
--- sql/Pg-central.sql	(revision 519)
+++ sql/Pg-central.sql	(revision 520)
@@ -14,7 +14,6 @@
                         countrycode text,
                         currency text,
                         dateformat text,
-                        dbconnect text,
                         dbdriver text default 'Pg',
                         dbhost text default 'localhost',
                         dbname text,
@@ -28,6 +27,7 @@
                         name text,
                         numberformat text,
                         password varchar(32) check(length(password) = 32),
+						crypted_password text,
                         print text,
                         printer text,
                         role text,
Index: menu.pl
===================================================================
--- menu.pl	(revision 519)
+++ menu.pl	(revision 520)
@@ -150,7 +150,6 @@
 1;
 # end
 
-
 sub check_password {
   
 	if ($myconfig{password}) {
@@ -158,7 +157,7 @@
 		require "bin/pw.pl";
 
 		if ($form->{password}) {
-			if ($myconfig{password} ne (Digest::MD5::md5_hex $form->{password})) {
+			if (! Session::password_check($form, $form->{login}, $form->{password})) {
 				if ($ENV{HTTP_USER_AGENT}) {
 					&getpassword;
 				} else {
@@ -178,12 +177,6 @@
 					$cookie{$name} = $value;
 				}
 
-				if ($form->{action} ne 'display') {
-					if ((! $cookie{"LedgerSMB-$form->{login}"}) || $cookie{"LedgerSMB-$form->{login}"} ne $form->{sessionid}) {
-						&getpassword(1);
-						exit;
-					}
-				}
 				#check for valid session
 				if(!Session::session_check($cookie{"LedgerSMB"}, $form)){
 					&getpassword(1);