import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / examples / LDAP / smbldap-tools / smbldap-passwd.pl
1 #!/usr/bin/perl -w
2
3 # LDAP to unix password sync script for samba
4
5 #  This code was developped by IDEALX (http://IDEALX.org/) and
6 #  contributors (their names can be found in the CONTRIBUTORS file).
7 #
8 #                 Copyright (C) 2001-2002 IDEALX
9 #
10 #  This program is free software; you can redistribute it and/or
11 #  modify it under the terms of the GNU General Public License
12 #  as published by the Free Software Foundation; either version 2
13 #  of the License, or (at your option) any later version.
14 #
15 #  This program is distributed in the hope that it will be useful,
16 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 #  GNU General Public License for more details.
19 #
20 #  You should have received a copy of the GNU General Public License
21 #  along with this program; if not, write to the Free Software
22 #  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 #  USA.
24
25 #  Purpose :
26 #       . ldap-unix passwd sync for SAMBA>2.2.2 + LDAP
27 #       . may also replace /bin/passwd
28
29 use strict;
30 use FindBin;
31 use FindBin qw($RealBin);
32 use lib "$RealBin/";
33 use smbldap_tools;
34 use smbldap_conf;
35
36 my $user;
37 my $oldpass;
38 my $ret;
39
40 my $arg;
41
42 foreach $arg (@ARGV) {
43   if ($< != 0) {
44         die "Only root can specify parameters\n";
45   } else {
46         if ( ($arg eq '-?') || ($arg eq '--help') ) {
47           print "Usage: $0 [username]\n";
48           print "  -?, --help                   show this help message\n";
49           exit (6);
50         } elsif (substr($arg,0) ne '-') {
51           $user = $arg;
52         }
53         $oldpass = 1;
54   }
55 }
56
57 if (!defined($user)) {
58   $user=$ENV{"USER"};
59 }
60
61 # test existence of user in LDAP
62 my $dn_line;
63 if (!defined($dn_line = get_user_dn($user))) {
64   print "$0: user $user doesn't exist\n";
65   exit (10);
66 }
67
68 my $dn = get_dn_from_line($dn_line);
69
70 my $samba = is_samba_user($user);
71
72 print "Changing password for $user\n";
73
74 # non-root user
75 if (!defined($oldpass)) {
76   # prompt for current password
77   system "stty -echo";
78   print "(current) UNIX password: ";
79   chomp($oldpass=<STDIN>);
80   print "\n";
81   system "stty echo";
82
83   if (!is_user_valid($user, $dn, $oldpass)) {
84         print "Authentication failure\n";
85         exit (10);
86   }
87 }
88
89 # prompt for new password
90
91 my $pass;
92 my $pass2;
93
94 system "stty -echo";
95 print "New password : ";
96 chomp($pass=<STDIN>);
97 print "\n";
98 system "stty echo";
99
100 system "stty -echo";
101 print "Retype new password : ";
102 chomp($pass2=<STDIN>);
103 print "\n";
104 system "stty echo";
105
106 if ($pass ne $pass2) {
107   print "New passwords don't match!\n";
108   exit (10);
109 }
110
111 # First, connecting to the directory
112 my $ldap_master=connect_ldap_master();
113
114 # only modify smb passwords if smb user
115 if ($samba == 1) {
116   if (!$with_smbpasswd) {
117         # generate LanManager and NT clear text passwords
118         if ($mk_ntpasswd eq '') {
119           print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
120           exit(1);
121         }
122         my $ntpwd = `$mk_ntpasswd '$pass'`;
123         chomp(my $sambaLMPassword = substr($ntpwd, 0, index($ntpwd, ':')));
124         chomp(my $sambaNTPassword = substr($ntpwd, index($ntpwd, ':')+1));
125         # the sambaPwdLastSet must be updating
126         my $date=time;
127         my @mods;
128         push(@mods, 'sambaLMPassword' => $sambaLMPassword);
129         push(@mods, 'sambaNTPassword' => $sambaNTPassword);
130         push(@mods, 'sambaPwdLastSet' => $date);
131         if (defined $_defaultMaxPasswordAge) {
132           my $new_sambaPwdMustChange=$date+$_defaultMaxPasswordAge*24*60*60;
133           push(@mods, 'sambaPwdMustChange' => $new_sambaPwdMustChange);
134           push(@mods, 'sambaAcctFlags' => '[U]');
135         }
136         # Let's change nt/lm passwords
137         my $modify = $ldap_master->modify ( "$dn",
138                                                                                 'replace' => { @mods }
139                                                                           );
140         $modify->code && warn "failed to modify entry: ", $modify->error ;
141
142   } else {
143         if ($< != 0) {
144           my $FILE="|$smbpasswd -s >/dev/null";
145           open (FILE, $FILE) || die "$!\n";
146           print FILE <<EOF;
147 '$oldpass'
148 '$pass'
149 '$pass'
150 EOF
151           ;
152           close FILE;
153         } else {
154           my $FILE="|$smbpasswd $user -s >/dev/null";
155           open (FILE, $FILE) || die "$!\n";
156           print FILE <<EOF;
157 '$pass'
158 '$pass'
159 EOF
160           ;
161           close FILE;
162         }
163   }
164 }
165
166 # change unix password
167 my $hash_password = `slappasswd -h {$hash_encrypt} -s '$pass'`;
168 chomp($hash_password);
169 my $modify = $ldap_master->modify ( "$dn",
170                                                                         changes => [
171                                                                                                 replace => [userPassword => "$hash_password"]
172                                                                                            ]
173                                                                   );
174 $modify->code && warn "Unable to change password : ", $modify->error ;
175
176 # take down session
177 $ldap_master->unbind;
178
179 exit 0;
180
181
182 # - The End
183
184 =head1 NAME
185        
186 smbldap-passwd.pl - change user password
187
188 =head1 SYNOPSIS
189        
190   smbldap-passwd.pl [name]
191
192 =head1 DESCRIPTION
193
194 smbldap-passwd.pl changes passwords for user accounts. A normal user
195        may only change the password for their own account, the super user may
196        change the password for any account.
197
198    Password Changes
199        The user is first prompted for their old password, if one is present.
200        This password is then tested against the stored password by binding
201        to the server. The user has only one chance to enter the correct pass-
202        word. The super user is permitted to bypass this step so that forgot-
203        ten passwords may be changed.
204
205        The user is then prompted for a replacement password. As a general
206        guideline, passwords should consist of 6 to 8 characters including
207        one or more from each of following sets:
208
209             Lower case alphabetics
210
211             Upper case alphabetics
212
213             Digits 0 thru 9
214
215             Punctuation marks
216
217        passwd will prompt again and compare the second entry against the first.
218        Both entries are require to match in order for the password to be
219        changed.
220
221 =head1 SEE ALSO
222
223        passwd(1)
224
225 =cut
226
227 #'