]>
git.proxmox.com Git - pmg-api.git/blob - PMG/UserConfig.pm
1 package PMG
::UserConfig
;
11 use PVE
::JSONSchema
qw(get_standard_option);
12 use PVE
::Exception
qw(raise);
16 my $inotify_file_id = 'pmg-user.conf';
17 my $config_filename = '/etc/pmg/user.conf';
22 my $class = ref($type) || $type;
24 my $cfg = PVE
::INotify
::read_file
($inotify_file_id);
26 return bless $cfg, $class;
32 PVE
::INotify
::write_file
($inotify_file_id, $self);
35 my $lockfile = "/var/lock/pmguser.lck";
38 my ($code, $errmsg) = @_;
40 my $p = PVE
::Tools
::lock_file
($lockfile, undef, $code);
42 $errmsg ?
die "$errmsg: $err" : die $err;
47 additionalProperties
=> 0,
49 userid
=> get_standard_option
('username'),
51 description
=> "Users E-Mail address.",
52 type
=> 'string', format
=> 'email',
56 description
=> "Account expiration date (seconds since epoch). '0' means no expiration date.",
63 description
=> "Flag to enable or disable the account.",
69 description
=> "Encrypted password (see `man crypt`)",
71 pattern
=> '\$\d\$[a-zA-Z0-9\.\/]+\$[a-zA-Z0-9\.\/]+',
75 description
=> "User role.",
77 enum
=> ['root', 'admin', 'qmanager', 'quser', 'audit'],
80 description
=> "First name.",
86 description
=> "Last name.",
92 description
=> "Keys for two factor auth (yubico).",
98 description
=> "Comment.",
105 our $update_schema = clone
($schema);
106 $update_schema->{properties
}->{role}->{optional
} = 1;
108 my $verity_entry = sub {
112 PVE
::JSONSchema
::check_prop
($entry, $schema, '', $errors);
113 if (scalar(%$errors)) {
114 raise
"verify entry failed\n", errors
=> $errors;
119 my ($filename, $fh) = @_;
127 while (defined(my $line = <$fh>)) {
128 next if $line =~ m/^\s*$/;
129 if ($line =~ m/^#(.*)$/) {
135 (?
<userid
>(?
:[^\s
:]+)) :
138 (?
<crypt_pass
>(?
:[^\s
:]*)) :
140 (?
<email
>(?
:[^\s
:]*)) :
141 (?
<first
>(?
:[^:]*)) :
147 userid
=> $+{userid
},
148 enable
=> $+{enable
} || 0,
149 expire
=> $+{expire
} || 0,
152 $d->{comment
} = $comment if $comment;
154 foreach my $k (qw(crypt_pass email first last keys)) {
155 $d->{$k} = $+{$k} if $+{$k};
159 $cfg->{$d->{userid
}} = $d;
162 warn "$filename: $err";
165 warn "$filename: ignore invalid line $.\n";
172 $cfg->{root
}->{userid
} = 'root';
173 $cfg->{root
}->{enable
} = 1;
174 $cfg->{root
}->{comment
} = 'Unix Superuser';
175 $cfg->{root
}->{role} = 'root';
176 delete $cfg->{root
}->{crypt_pass
};
181 sub write_user_conf
{
182 my ($filename, $fh, $cfg) = @_;
186 delete $cfg->{root
}->{crypt_pass
};
188 foreach my $userid (keys %$cfg) {
189 my $d = $cfg->{$userid};
190 $d->{userid
} = $userid;
193 $cfg->{$d->{userid
}} = $d;
198 my $line = "$userid:";
199 for my $k (qw(enable expire crypt_pass role email first last keys)) {
200 $line .= ($d->{$k} // '') . ':';
202 $raw .= $line . "\n";
205 PVE
::Tools
::safe_print
($filename, $fh, $raw);
208 PVE
::INotify
::register_file
($inotify_file_id, $config_filename,
212 always_call_parser
=> 1);
214 sub lookup_user_data
{
215 my ($self, $username, $noerr) = @_;
217 return $self->{$username} if $self->{$username};
219 die "no such user ('$username')\n" if !$noerr;
224 sub authenticate_user
{
225 my ($self, $username, $password) = @_;
227 die "no password\n" if !$password;
229 my $data = $self->lookup_user_data($username);
232 my $expire = $data->{expire
};
234 die "account expired\n" if $expire && ($expire < $ctime);
236 if ($data->{crypt_pass
}) {
237 my $encpw = crypt($password, $data->{crypt_pass
});
238 die "invalid credentials\n" if ($encpw ne $data->{crypt_pass
});
240 die "no password set\n";
247 my ($class, $username, $password) = @_;
250 my $cfg = $class->new();
251 my $data = $cfg->lookup_user_data($username); # user exists
252 my $epw = PMG
::Utils
::encrypt_pw
($password);
253 $data->{crypt_pass
} = $epw;