Skip to content

Commit 55ffb15

Browse files
committed
Shared web script for changing passwords using smbldap-tools
1 parent 59350c5 commit 55ffb15

1 file changed

Lines changed: 179 additions & 0 deletions

File tree

smbldap-tools/passwd.cgi

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#!/usr/bin/perl -w
2+
3+
#
4+
# Addon for smbldap-tools: Change password via Web
5+
#
6+
# Distribution under the same conditions as smbldap-tools
7+
#
8+
# (c) 2009, Gerrit Beine <gerrit.beine@gmx.de>
9+
#
10+
11+
use strict;
12+
use CGI;
13+
14+
use lib "/usr/sbin";
15+
use smbldap_tools;
16+
17+
use Crypt::SmbHash;
18+
use Digest::MD5 qw(md5);
19+
use Digest::SHA1 qw(sha1);
20+
use MIME::Base64 qw(encode_base64);
21+
22+
my $query = new CGI();
23+
my @parameter = $query->param();
24+
25+
if ( $#parameter == 3 ) {
26+
change_password($query);
27+
} else {
28+
show_form($query);
29+
}
30+
31+
exit;
32+
33+
sub show_form($) {
34+
my $response = shift;
35+
print $response->header(),
36+
$response->start_html('Change Password'),
37+
$response->h1('Change Password'),
38+
$response->start_form(),
39+
"Username: ",
40+
$response->textfield('username', '', 50, 80),
41+
$response->p(),
42+
"Old password: ",
43+
$response->password_field('oldpassword', '*****', 50, 80),
44+
$response->p(),
45+
"New password: ",
46+
$response->password_field('newpassword', '*****', 50, 80),
47+
$response->p(),
48+
"Verify new password: ",
49+
$response->password_field('verifypassword', '*****', 50, 80),
50+
$response->p(),
51+
$response->submit(),
52+
$response->end_form(),
53+
$response->end_html();
54+
}
55+
56+
sub show_response($$) {
57+
my $response = shift;
58+
my $message = shift;
59+
print $response->header(), $message;
60+
61+
}
62+
63+
sub change_password($) {
64+
my $request = shift;
65+
66+
my $username = $request->param('username');
67+
my $oldpassword = $request->param('oldpassword');
68+
my $newpassword = $request->param('newpassword');
69+
my $verifypassword = $request->param('verifypassword');
70+
71+
if ( $newpassword ne $verifypassword ) {
72+
show_response($request, "Error: new password does not match verification password.");
73+
exit;
74+
}
75+
76+
$config{masterDN} = "uid=$username,$config{usersdn}";
77+
$config{masterPw} = "$oldpassword";
78+
my $ldap_master = connect_ldap_master();
79+
my $dn = $config{masterDN};
80+
if ( ! is_user_valid($username, $dn, $oldpassword) ) {
81+
show_response($request, "Error: authentication failure.");
82+
exit;
83+
}
84+
85+
my $samba = is_samba_user($username);
86+
87+
if ($samba) {
88+
my ($sambaLMPassword, $sambaNTPassword) = ntlmgen($newpassword);
89+
my @mods = (
90+
'sambaLMPassword' => $sambaLMPassword,
91+
'sambaNTPassword' => $sambaNTPassword,
92+
'sambaPwdLastSet' => time()
93+
);
94+
my $modify = $ldap_master->modify( $dn, 'replace' => { @mods } );
95+
if ( $modify->code ) {
96+
show_response($request, "Error: failed changing Samba password.\nReason: " . $modify->error );
97+
exit;
98+
}
99+
}
100+
101+
my $hash_password = make_hash($newpassword, $config{hash_encrypt}, $config{crypt_salt_format});
102+
my $shadowLastChange = int(time()/86400);
103+
104+
my @mods = (
105+
'userPassword' => $hash_password,
106+
'shadowLastChange' => $shadowLastChange
107+
);
108+
my $modify = $ldap_master->modify( $dn, 'replace' => { @mods } );
109+
if ( $modify->code ) {
110+
show_response($request, "Error: failed changing Unix password.\nReason: " . $modify->error );
111+
exit;
112+
}
113+
114+
if ( $samba ) {
115+
show_response($request, "Success: changed Samba and Unix password" );
116+
} else {
117+
show_response($request, "Success: changed Unix password" );
118+
}
119+
}
120+
121+
# Generates hash to be one of the following RFC 2307 schemes:
122+
# CRYPT, MD5, SMD5, SHA, SSHA, and CLEARTEXT
123+
# SSHA is default
124+
# '%s' is a default crypt_salt_format
125+
# A substitute for slappasswd tool
126+
sub make_hash
127+
{
128+
my $hash_encrypt;
129+
my $crypt_salt_format;
130+
131+
my $clear_pass=$_[0] or return undef;
132+
$hash_encrypt='{' . $_[1] . '}' or $hash_encrypt = "{SSHA}";
133+
$crypt_salt_format=$_[2] or $crypt_salt_format = '%s';
134+
135+
my $hash_pass;
136+
if ($hash_encrypt eq "{CRYPT}" && defined($crypt_salt_format)) {
137+
# Generate CRYPT hash
138+
# for unix md5crypt $crypt_salt_format = '$1$%.8s'
139+
my $salt = sprintf($crypt_salt_format,make_salt());
140+
$hash_pass = "{CRYPT}" . crypt($clear_pass,$salt);
141+
142+
} elsif ($hash_encrypt eq "{MD5}") {
143+
# Generate MD5 hash
144+
$hash_pass = "{MD5}" . encode_base64( md5($clear_pass),'' );
145+
146+
} elsif ($hash_encrypt eq "{SMD5}") {
147+
# Generate SMD5 hash (MD5 with salt)
148+
my $salt = make_salt(4);
149+
$hash_pass = "{SMD5}" . encode_base64( md5($clear_pass . $salt) . $salt,'');
150+
151+
} elsif ($hash_encrypt eq "{SHA}") {
152+
# Generate SHA1 hash
153+
$hash_pass = "{SHA}" . encode_base64( sha1($clear_pass),'' );
154+
155+
} elsif ($hash_encrypt eq "{SSHA}") {
156+
# Generate SSHA hash (SHA1 with salt)
157+
my $salt = make_salt(4);
158+
$hash_pass = "{SSHA}" . encode_base64( sha1($clear_pass . $salt) . $salt,'' );
159+
160+
} elsif ($hash_encrypt eq "{CLEARTEXT}") {
161+
$hash_pass=$clear_pass;
162+
163+
} else {
164+
$hash_pass=undef;
165+
}
166+
return $hash_pass;
167+
}
168+
169+
# Generates salt
170+
# Similar to Crypt::Salt module from CPAN
171+
sub make_salt
172+
{
173+
my $length=32;
174+
$length = $_[0] if exists($_[0]);
175+
176+
my @tab = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
177+
return join "",@tab[map {rand 64} (1..$length)];
178+
}
179+

0 commit comments

Comments
 (0)