Solved

Password once only

Posted on 2002-04-11
15
416 Views
Last Modified: 2012-06-19
I would like to "sell" access through a password to a pdf-file, but somehow i want the password to be "consumed" after one use. That is, i don't want the users to be able to pass the PW along to all their friends for a multitude of downloads.
Is there a way in Perl to allow a PW to be sent by e-mail, allow the user to download the file once, but then no more?

Best,
Al
0
Comment
Question by:algabatz
  • 8
  • 3
  • 3
  • +1
15 Comments
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
yaou can do sth like this :


Give the pass:
1. Generate encoded password
2.1 Send it to the users email
2.2 Save it to local file

Users login:
1. Check if the password match to any of the passwords in the local file
If no :
2. deny access
If so :
2. read the pdf and print it to the user
3. delete his password from the local file


0
 
LVL 1

Author Comment

by:algabatz
Comment Utility
Sounds great. tricky part is to write the code...

/Al
0
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
OK  I'll write the code for you :)but just pls give me some time becouse I have no time now.

I hope to do it till tommorow :) is it OK ?
0
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
pls tel me also can you use sendmail? what is  the web server?  the OS ? Perl version ?
0
 
LVL 1

Author Comment

by:algabatz
Comment Utility
Sendmail yes, Apache, dunno right off th version.
I'll try to check.

Best,
Al
0
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
OK :)

it's ready
It folows the scheme I gave you:
##########################################################
Give the pass (give.cgi):
1. Generate encoded password
2.1 Send it to the users email
2.2 Save it to local file

Users login (login.cgi):
1. Check if the password match to any of the passwords in the local file
If no :
2. deny access
If so :
2. read the pdf and print it to the user
3. delete his password from the local file
##########################################################



1st script - give the pass :
##########################################################
#!/usr/bin/perl
# give.cgi
use strict;
use warnings;
use Fcntl qw(:flock);

# Initialize variables
my $recipient = 'so@email.com';
my $pass_file=".passwords";
my $sendmail = '/usr/bin/sendmail';
my $pass;



# Generate random password
$pass = crypt localtime, join "", (0..9, 'A'..'Z', 'a'..'z')[rand 62, rand 62];
$pass=~s/\W/_/g;


# Save the pass to the pass file
open FILE, ">>$pass_file" or die "can't open pass file \n $!\n";
flock FILE, LOCK_EX;
print  FILE $pass, "\n";
flock FILE, LOCK_UN;  
close FILE;


# Send it to the user's email
open (SENDMAIL, "| $sendmail -t -n") or die "can't open $sendmail !\n $!";
#*SENDMAIL=STDOUT; #for test purposes (prints the mail  to STDOUT instead sending it)

# Configure these to match your info
print SENDMAIL <<End_of_Mail;
From: your name here
To: $recipient
Reply-To: your_email\@email.com
Subject: your password bla bla  bla

Your password is $pass. blablabla bla bla bla
Please note that it is valid only for one download ...
bla bla bla ...
End_of_Mail

# End -->
##########################################################



Exapmle login.html
##########################################################
<HTML>
<HEAD>
<TITLE>Login</TITLE>
</HEAD>
<BODY bgcolor="#FFFFFF" text="#000000">
enter your password:
<FORM name="form1" method="post" action="http://mydomain.com/cgi-bin/login.cgi/file.zip">
  <INPUT type="password" name="user_pass">
  <INPUT type="submit" name="Submit" value="Submit">
</FORM>
</BODY>
</HTML>
##########################################################



the 2d perl script - login.cgi:
##########################################################
#!/usr/bin/perl
# login.cgi
use strict;
use warnings;
use Fcntl qw(:flock);
use CGI;

my $bad_page='htpp://yourdomain.com/badlogin.htm';
my $protected_file='thefile.zip';
my $pass_file='.passwords';
my @passwords;

# Let say the user enters the password in form field called "user_pass"
my $q=new CGI;
my $user_pass = $q->param("user_pass");



# Get the passwords from the file:
open DATFILE, "<$pass_file" or die "can't open $pass_file \n $!\n";
@passwords=<DATFILE>;
close DATFILE;
chomp @passwords;


# Check if the entered pass is OK (exist in the file):
if (grep {$_ eq $user_pass} @passwords) {
    return_protected_file(); # give  file to the user
    update_passfile(); #remove it from the pass file
} else {
    print $q->redirect($bad_page); # redirect to bad pass page
}


sub update_passfile {
    # Open the file and print all @paswords but without the used one
    open FILE, ">$pass_file" or die "can't open pass file \n $!\n";
    flock FILE, LOCK_EX;
    local $,="\n";
    print FILE grep {$_ ne $user_pass} @passwords;
    flock FILE, LOCK_UN;
    close FILE;
}

sub return_protected_file {
   # Read the file and print it to user:
    undef $/;
    open FILE, "<$protected_file" or die "can't open $protected_file! \n$!\n";
    binmode FILE;

    print "Content-Type: application/zip\n\n";

    binmode STDOUT;
    print  STDOUT <FILE>;
}


# End -->
0
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
OK now it's your turn - configure it to match your setings, upload, chmode 755 and that's it ! :))

:)))
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Author Comment

by:algabatz
Comment Utility
Excellent! I'll give it a run and get back to you.

/Al
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
Careful with that, if two users try to run that program at the same time, it can truncate $pass_file
I'd suggest instead of having $pass_file contain $user_pass, you use $user_pass as a file name.
0
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
Ozo, the file has exclusive lock
it will look ugly to have 200+ empty textfiles just for that app :)
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
Your exclusive lock is applied after the file has already been truncated.
0
 
LVL 3

Expert Comment

by:Tsvetomir
Comment Utility
Yes! but the info is already in the script and is imediately writen !
You know that that's the idea it has to be like that.

All info needed is already in array @passwords then we open the pass file , "truncate" the old thata (cos' it old!) and print the new one ! then save the file with the updated data ! Where is the problem !? - that's the idea !  


I'm sure that as may be the most advanced here you perfectly understand that ! :)...  are you joking or sth :)???
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
In between the truncation and the write, another program can do a read of the empty file,
0
 
LVL 3

Accepted Solution

by:
Tsvetomir earned 300 total points
Comment Utility
Are you talking about the possibility the 2d user to read the file after it's truncated - to remember  the empty list and write it in the file when the lock is released ????
(this means to accees it when the execution of the sript is between lines  open FILE... and   flock FILE ... !!!)


The chance for this is smaller then wining from the lotery ! :)

but ... as usual:

Yes...  Ozo, I agree with you.  This is realy the better way.
(just may be not the easyest ...)

OK here is the new  script (I also fixed a litle bug that I found in the previous) :



##########################################################
#!/usr/bin/perl
# login.cgi
use strict;
use warnings;
use Fcntl qw(:flock);
use CGI;

my $bad_page='htpp://yourdomain.com/badlogin.htm';
my $protected_file='thefile.zip';
my $pass_file='.passwords';
my @passwords;

# Let say the user enters the password in form field called "user_pass"
my $q=new CGI;
my $user_pass = $q->param("user_pass");



# Get the passwords from the file:
# Open it for read/write  access (doesn't flush the current data)
open FILE, "+<$pass_file" or die "can't open pass file \n $!\n";
# Lock it from the very begining !
flock FILE, LOCK_EX;
@passwords=<FILE>;
chomp @passwords;

# Check if the entered pass is OK (exist in the file):
if (grep {$_ eq $user_pass} @passwords) {
    return_protected_file();
    update_passfile();
} else {
    close FILE;
    print $q->redirect($bad_page);
}


sub update_passfile {
    # print the rest passwords - all @paswords but without the used one
    my @rest = grep {$_ ne $user_pass and $_ ne ""} @passwords;
    # Tha main changes here we delete the previous old but data but now the file is already locked!
    seek FILE, 0 , 0;
    truncate FILE, 0;      

    local $,="\n";
    print FILE @rest;
    print FILE "\n" if @rest;  
    flock FILE, LOCK_UN;
    close FILE;
}

sub return_protected_file {
   # Read the file and print it to user:
    undef $/;
    open FILE, "<$protected_file" or die "can't open $protected_file! \n$!\n";
    binmode FILE;

    print "Content-Type: application/zip\n\n";

    binmode STDOUT;
    print  STDOUT <FILE>;
}


# End -->




OK how is that ?
:)
0
 

Expert Comment

by:larsan
Comment Utility
I haven't done any programming in years but I wanted to revive this script.
Now I can't get anything to work.
Please help me sort out with which file goes where and if there's a html missing?
Do I need to add a document for the generated passwords?
If the "secret" document is called secret.doc should it be in cgi-bin?

/Al
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now