Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Passwd, shadow and htpasswd 1

Status
Not open for further replies.

timgerr

IS-IT--Management
Jan 22, 2004
364
US
I was wondering if there was a way to sync my htpasswd passwords with /etc/passwd and /etc/shadow. I want to create a single sign on without going LDAP.

Thanks,
timgerr

-How important does a person have to be before they are considered assassinated instead of just murdered?
-Need more cow bell!!!

 
The htpasswd field format can accept sha or md5 hashes and uses a the familiar username:password format. Importing the username and passwd fields from shadow is as simple as:

Code:
awk -F: '/usernamehere/ {printf "%s:%s\n",$1,$2}' /etc/shadow >> apache_pw_file
 
What is the least (minimal) level of permissions for a htpasswd file. Who needs access to it can how can I prevent other people from viewing it?

Thanks,
timgerr

-How important does a person have to be before they are considered assassinated instead of just murdered?
-Need more cow bell!!!

 
The httpd user needs to be able to read and execute as do the user(s) in question.
 
httpd needs to execute?!!?!? really? I thought .htpasswd was read by the "Apache" or "httpd" or "nobody" user that is running the httpd daemon/service... limited exception might be .cgi scripts that are running setuid. And Execute? nothing to execute...

I tend to leave my .htpasswd files as chmod 644 and have no issues, that's probably sloppy and should be 640 or 600 or even 400.

D.E.R. Management - IT Project Management Consulting
 
I tried without execute permissions for PHP enabled apps and ran into issues. YMMV.
 
Here is a perl script that I wrote that will search for a username in /etc/shadow and add that person to a htpasswd file. It might not be the cleanest thing but it works
Code:
#!/usr/bin/perl
use strict;
#use warnings;
## Global my
my @returnHash;
my($foundUserName, $foundHash);
my @htpasswdFileRead;
my $htpasswdPath;
my @extractUser;
my $uName;
my $thisSearch;
my $thisHash;
my $httpPasswordFile;
my @readAll;
my $num;
my @readAllSplit;
my $enterCommand;
## Adding the sub rutienes
sub editHtpasswdFile;
sub findInShadow;
sub findInHtpasswd;

## FindInShadow will take a username and line from the shadow file to see if the user name is in the shadow file.  If yes then the rutien will return the username and hash within an array
sub findInShadow
{
	## This search each line for the username that is supplied and 
	## return it
	($uName,$thisSearch) = @_;
	chomp($uName,$thisSearch);
	@extractUser = split(/:/,$thisSearch);
	if($extractUser[0] eq  $uName && length($extractUser[1]) > 0 ){
		print "Found the user " . $extractUser[0] . " in /etc/shadow" . "\n";
		push(@returnHash, $extractUser[0]);
		push(@returnHash, $extractUser[1]);
		print 'returning hash' . "\n";
#		return(@returnHash);
	}
	
		return(@returnHash);
}

sub findInHtpasswd
{
	($uName,$thisHash,$thisSearch,$httpPasswordFile) = @_;
        chomp($uName,$thisSearch);
	@extractUser = split(/:/,$thisSearch);
	if($extractUser[0] eq  $uName && length($extractUser[1]) > 0 ){
        	print "Found the user " . $extractUser[0] ."in " . $httpPasswordFile ."\n";
		if($extractUser[0] eq  $uName && $extractUser[1] ne $thisHash){
			print 'Hash is different' . "\n";
			## Now we are going to edit the htpasswd file with the 
			## updated hash
			editHtpasswdFile $uName,$thisHash,$httpPasswordFile;
		}else{
			print "Hash is the same \n";
		}
	}

}

sub editHtpasswdFile
{
	($uName,$thisHash,$httpPasswordFile) = @_;
	chomp($uName,$thisHash,$httpPasswordFile);
	open(WHOLE,$httpPasswordFile) || die("could not open " . $httpPasswordFile . "\n");
	@readAll = <WHOLE>;
	close(WHOLE);
	## Before we do anyting we need to rotate the file
	system("/sbin/rotate.pl " . $httpPasswordFile);
	## We need to delete all the users in the htpasswd file.  
	open(KILLME,">$httpPasswordFile") || die "could not open file";
	print KILLME '';
	close(KILLME);
	
	## Now that we have all the information in the array we need to 
	## delete the non synced user hash
	$num = 0;
	foreach(@readAll){
		@readAllSplit = split(/:/,$_);
		if($readAllSplit[0] eq $uName){
#			$readAll[$num] = $uName  . ":" .  $thisHash . "\n";
			$readAll[$num] = '';
		}
		$num++;
	}
	## Now I have to open the htpasswd file and write back to it
	open(WRITETO,">>$httpPasswordFile");
	print WRITETO @readAll;
	close(WRITETO);
	## Going to write the user that we are looking for
	## The reason why I use the awk command is that perl dosnt like some of the encrypted 
	## charictors
	$enterCommand = "awk -F: \'/$uName/ {printf \"%s:%s\\n\",\$1,\$2}\' /etc/shadow >> $httpPasswordFile";
	system($enterCommand);


}




## This will check to see if two arguments where supplied
if(scalar(@ARGV) != 2){
	print "ERROR: Please enter a user name and htpasswd file to sync!!!";
	print "\n";
	print "Like psync jane.doe /somthing/somthing\n";
	exit;
}

## Opening the shadow file and getting all the information 
my $userName = $ARGV[0];
open(RFILE,'/etc/shadow');
my @readFile = <RFILE>;
close(RFILE);
my @shadowUser;
foreach(@readFile){
	## This will send every shasow line to a sub to see if the user
	## name is in it. If found it will return a user and a hash	
	($foundUserName, $foundHash) = findInShadow $userName,$_;

}
## Going to test to see if the two returned variables have a user name
## and a password
print $foundUserName . " -  " . $foundHash . "\n";
if(length($foundUserName) == 0  && length($foundHash) == 0){
	print "ERROR: Problem finding account or password for  " . $userName . "\n" ;
}
## Now that we have a confirmed that a user exists in the shadow and the information is located within the $foundUserName, $foundHash variables, lets look for the same infomation in the htpasswd files.  

## Lets take the confirmed username and see if it is in the htpasswd file
## We are going to open the htpasswd file and put all the data into an array
$htpasswdPath = $ARGV[1];
open(RHPD,$htpasswdPath) || die('ERROR: could not open ' . $htpasswdPath);
@htpasswdFileRead = <RHPD>;
close(RHPD);
foreach(@htpasswdFileRead){
	findInHtpasswd $foundUserName,$foundHash, $_, $htpasswdPath;
#	print $_;
}

timgerr

-How important does a person have to be before they are considered assassinated instead of just murdered?
-Need more cow bell!!!

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top