2 # Functions for freebsd format last output
4 $netinfo_domain = $config{'netinfo_domain'} || ".";
6 # Mapping from OSX user properties to Webmin user hash keys
7 %user_properties_map = (
8 'RecordName' => 'user',
10 'PrimaryGroupID' => 'gid',
12 'NFSHomeDirectory' => 'home',
13 'UserShell' => 'shell',
16 # And to group hash keys
17 %group_properties_map = (
18 'RecordName' => 'group',
19 'PrimaryGroupID' => 'gid',
20 'GroupMembership' => 'members',
24 # Returns 6 for macos netinfo user storage, 7 for new directory service
27 if (-x "/usr/bin/nidump") {
28 # Old netinfo format users DB
31 elsif (-x "/usr/bin/dscl") {
32 # New directory service DB
41 # Returns 5 for macos netinfo group storage, 7 for new directory service
44 if (-x "/usr/bin/nidump") {
45 # Old netinfo format groups DB
48 elsif (-x "/usr/bin/dscl") {
49 # New directory service DB
57 # open_last_command(handle, user)
60 local ($fh, $user) = @_;
61 open($fh, "last $user |");
64 # read_last_line(handle)
65 # Parses a line of output from last into an array of
66 # user, tty, host, login, logout, period
72 if (!$line) { return (); }
73 if ($line =~ /^(reboot|shutdown)/) { next; }
74 if ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+)\s+\-\s+(\S+)\s+\((\d+:\d+)\)/) {
75 return ($1, $2, $3, $4, $5 eq "shutdown" ? "Shutdown" :
76 $5 eq "crash" ? "Crash" : $5, $6);
78 elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+)\s+still/) {
79 return ($1, $2, $3, $4);
84 # execute_dscl_command(command, arg, ...)
85 # Executes some batch command with dscl, and calls error on failure
86 sub execute_dscl_command
88 local ($cmd, @args) = @_;
89 local $fullcmd = "dscl '$netinfo_domain' ".quotemeta($cmd);
90 foreach my $a (@args) {
91 $fullcmd .= " ".($a eq '' ? "''" : quotemeta($a));
93 local $out = &backquote_command("$fullcmd 2>&1 </dev/null");
95 &error("<tt>".&html_escape($fullcmd)."</tt> failed : ".
96 "<tt>".&html_escape($out)."</tt>");
101 # get_macos_password_hash(uid)
102 # Given a user's ID, return the password hash. This is in SHA1 format, and the
103 # first 4 bytes are the salt
104 sub get_macos_password_hash
107 return undef if (!$uuid);
108 local $hashfile = &read_file_contents("/var/db/shadow/hash/$uuid");
110 return substr($hashfile, 169, 48);
115 # set_macos_password_hash(uuid, hash)
116 # Updates the password hash for some OSX user
117 sub set_macos_password_hash
119 local ($uuid, $pass) = @_;
120 print STDERR "uuid=$uuid hash=$pass\n";
121 return 0 if (!$uuid);
122 local $hashfile = &read_file_contents("/var/db/shadow/hash/$uuid");
124 if (length($pass) > 48) {
125 $pass = substr($pass, 0, 48);
127 elsif (length($pass) < 48) {
128 $pass .= ("0" x (48-length($pass)));
130 substr($hashfile, 169, 48) = $pass;
131 &open_tempfile(HASHFILE, ">/var/db/shadow/hash/$uuid");
132 &print_tempfile(HASHFILE, $hashfile);
133 &close_tempfile(HASHFILE);