NAME
Unix::Passwd::File - Manipulate /etc/{passwd,shadow,group,gshadow} entries
VERSION
version 0.03
SYNOPSIS
use Unix::Passwd::Files;
# list users. by default uses files in /etc (/etc/passwd, /etc/shadow, et al)
my $res = list_users(); # [200, "OK", ["root", ...]]
# change location of files, return details
$res = list_users(etc_dir=>"/some/path", detail=>1);
# [200, "OK", [{user=>"root", uid=>0, ...}, ...]]
# also return detail, but return array entries instead of hash
$res = list_users(detail=>1, with_field_names=>0);
# [200, "OK", [["root", "x", 0, ...], ...]]
# get user/group information
$res = get_group(user=>"buzz"); # [200, "OK", {user=>"buzz", uid=>501, ...}]
$res = get_user(user=>"neil"); # [404, "Not found"]
# check whether user/group exists
say user_exists(user=>"buzz"); # 1
say group_exists(group=>"neil"); # 0
# get all groups that user is member of
$res = get_user_groups(user=>"buzz"); # [200, "OK", ["buzz", "nasa"]]
# check whether user is member of a group
$res = is_member(user=>"buzz", group=>"nasa"); # 1
# adding user/group, by default adding user will also add a group with the same
# name
$res = add_user (user =>"steven", ...); # [200, "OK", {uid=>540, gid=>541}]
$res = add_group(group=>"steven", ...); # [412, "Group already exists"]
# modify user/group
$res = modify_user(user=>"steven", home=>"/newhome/steven"); # [200, "OK"]
$res = modify_group(group=>"neil"); # [404, "Not found"]
# deleting user will also delete user's group
$res = delete_user(user=>"neil");
# change user password
$res = set_user_password(user=>"steven", pass=>"foobar");
$res = modify_user(user=>"steven", pass=>"foobar"); # same thing
# add/delete user to/from group
$res = add_user_to_group(user=>"steven", group=>"wheel");
$res = delete_user_from_group(user=>"steven", group=>"wheel");
# others
$res = get_max_uid(); # [200, "OK", 65535]
$res = get_max_gid(); # [200, "OK", 65534]
DESCRIPTION
This module can be used to read and manipulate entries in Unix system password files (/etc/passwd, /etc/group, /etc/group, /etc/gshadow; but can also be told to search in custom location, for testing purposes).
SEE ALSO
Old modules on CPAN which do not support shadow files are pretty useless to me (e.g. Unix::ConfigFile). Shadow passwords have been around since 1988 (and in Linux since 1992), FFS!
Passwd::Unix. I created a fork of Passwd::Unix v0.52 called Passwd::Unix::Alt in 2011 to fix some of the deficiencies/quirks in Passwd::Unix, including: lack of tests, insistence of running as root (despite allowing custom passwd files), use of not-so-ubiquitous bzip2, etc. Then in 2012 I decided to create Unix::Passwd::File. Here are how Unix::Passwd::File differs compared to Passwd::Unix (and Passwd::Unix::Alt):
tests in distribution
no need to run as root
no need to be able to read the shadow file for some operations
For example,
list_users()
will simply not return theencpass
field if the shadow file is unreadable. Of course, access to shadow file is required when getting or setting password.strictly procedural (non-OO) interface
I consider this a feature :-)
detailed error message for each operation
removal of global error variable
working locking
Locking is done by locking
passwd.lock
file.
Setup::Unix::User and Setup::Unix::Group, which use this module.
FUNCTIONS
add_group(%args) -> [status, msg, result, meta]
Add a new group.
Arguments ('*' denotes required arguments):
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.etc_dir* => str (default: "/etc")
Specify location of passwd files.
gid => any
Pick a specific new GID.
group => any
max_gid => any
Pick a range for new GID.
members => any
Fill initial members.
min_gid => any
Pick a range for new GID.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
add_user(%args) -> [status, msg, result, meta]
Add a new user.
Arguments ('*' denotes required arguments):
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.encpass* => str
Encrypted password.
etc_dir* => str (default: "/etc")
Specify location of passwd files.
expire_date => int
The date of expiration of the account, expressed as the number of days since Jan 1, 1970.
gecos* => str
Usually, it contains the full username.
gid => any
Pick a specific new GID.
home* => str
User's home directory.
last_pwchange => int
The date of the last password change, expressed as the number of days since Jan 1, 1970..
max_gid => any
Pick a range for new GID.
max_pass_age => int
The number of days after which the user will have to change her password.
max_uid => any
Pick a range for new UID.
min_gid => any
Pick a range for new GID.
min_pass_age => int
The number of days the user will have to wait before she will be allowed to change her password again.
min_uid => any
Pick a range for new UID.
pass* => str
Password, generally should be "x" which means password is encrypted in shadow.
pass_inactive_period => int
The number of days after a password has expired (see max_pass_age) during which the password should still be accepted (and user should update her password during the next login).
pass_warn_period => int
The number of days before a password is going to expire (see max_pass_age) during which the user should be warned.
shell* => str
User's home directory.
uid => any
Pick a specific new UID.
user => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
add_user_to_group(%args) -> [status, msg, result, meta]
Add user to a group.
Arguments ('*' denotes required arguments):
group => any
user => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
delete_group(%args) -> [status, msg, result, meta]
Delete a group.
Arguments ('*' denotes required arguments):
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.etc_dir* => str (default: "/etc")
Specify location of passwd files.
group => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
delete_user(%args) -> [status, msg, result, meta]
Delete a user.
Arguments ('*' denotes required arguments):
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.etc_dir* => str (default: "/etc")
Specify location of passwd files.
user => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
delete_user_from_group(%args) -> [status, msg, result, meta]
Delete user from a group.
Arguments ('*' denotes required arguments):
group => any
user => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
get_group(%args) -> [status, msg, result, meta]
Get group details by group name or gid.
Either group
OR gid
must be specified.
The function is not dissimilar to Unix's getgrnam()
or getgrgid()
.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
gid* => int
group* => str
with_field_names => bool (default: 1)
If false, don't return hash.
By default, a hashref is returned containing field names and its values, e.g.
{group=
"neil", pass=>"x", gid=>500, ...}>. Withwith_field_names=
0>, an arrayref is returned instead:["neil", "x", 500, ...]
.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
get_max_gid(%args) -> [status, msg, result, meta]
Get maximum GID used.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
get_max_uid(%args) -> [status, msg, result, meta]
Get maximum UID used.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
get_user(%args) -> [status, msg, result, meta]
Get user details by username or uid.
Either user
OR uid
must be specified.
The function is not dissimilar to Unix's getpwnam()
or getpwuid()
.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
uid* => int
user* => str
with_field_names => bool (default: 1)
If false, don't return hash.
By default, a hashref is returned containing field names and its values, e.g.
{user=
"neil", pass=>"x", uid=>500, ...}>. Withwith_field_names=
0>, an arrayref is returned instead:["neil", "x", 500, ...]
.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
get_user_groups(%args) -> [status, msg, result, meta]
Return groups which the user belongs to.
Arguments ('*' denotes required arguments):
detail => bool (default: 0)
If true, return all fields instead of just group names.
etc_dir* => str (default: "/etc")
Specify location of passwd files.
user => any
with_field_names => bool (default: 1)
If false, don't return hash for each entry.
By default, when
detail=
1>, a hashref is returned for each entry containing field names and its values, e.g.{group=
"neil", pass=>"x", gid=>500, ...}>. Withwith_field_names=
0>, an arrayref is returned instead:["neil", "x", 500, ...]
.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
group_exists(%args) -> [status, msg, result, meta]
Check whether group exists.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
gid* => int
group* => str
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
is_member(%args) -> [status, msg, result, meta]
Check whether user is member of a group.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
group => any
user => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
list_groups(%args) -> [status, msg, result, meta]
List Unix groups in group file.
Arguments ('*' denotes required arguments):
detail => bool (default: 0)
If true, return all fields instead of just group names.
etc_dir* => str (default: "/etc")
Specify location of passwd files.
with_field_names => bool (default: 1)
If false, don't return hash for each entry.
By default, when
detail=
1>, a hashref is returned for each entry containing field names and its values, e.g.{group=
"neil", pass=>"x", gid=>500, ...}>. Withwith_field_names=
0>, an arrayref is returned instead:["neil", "x", 500, ...]
.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
list_users(%args) -> [status, msg, result, meta]
List Unix users in passwd file.
Arguments ('*' denotes required arguments):
detail => bool (default: 0)
If true, return all fields instead of just usernames.
etc_dir* => str (default: "/etc")
Specify location of passwd files.
with_field_names => bool (default: 1)
If false, don't return hash for each entry.
By default, when
detail=
1>, a hashref is returned for each entry containing field names and its values, e.g.{user=
"neil", pass=>"x", uid=>500, ...}>. Withwith_field_names=
0>, an arrayref is returned instead:["neil", "x", 500, ...]
.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
modify_group(%args) -> [status, msg, result, meta]
Modify an existing group.
Specify arguments to modify corresponding fields. Unspecified fields will not be modified.
Arguments ('*' denotes required arguments):
admins* => str
It must be a comma-separated list of user names, or empty.
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.encpass* => str
Encrypted password.
etc_dir* => str (default: "/etc")
Specify location of passwd files.
gid* => int
Numeric group ID.
group* => str
Group name.
members* => str
List of usernames that are members of this group, separated by commas.
pass* => str
Password, generally should be "x" which means password is encrypted in gshadow.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
modify_user(%args) -> [status, msg, result, meta]
Modify an existing user.
Specify arguments to modify corresponding fields. Unspecified fields will not be modified.
Arguments ('*' denotes required arguments):
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.encpass* => str
Encrypted password.
etc_dir* => str (default: "/etc")
Specify location of passwd files.
expire_date => int
The date of expiration of the account, expressed as the number of days since Jan 1, 1970.
gecos* => str
Usually, it contains the full username.
gid* => int
Numeric primary group ID for this user.
home* => str
User's home directory.
last_pwchange => int
The date of the last password change, expressed as the number of days since Jan 1, 1970..
max_pass_age => int
The number of days after which the user will have to change her password.
min_pass_age => int
The number of days the user will have to wait before she will be allowed to change her password again.
pass* => str
Password, generally should be "x" which means password is encrypted in shadow.
pass_inactive_period => int
The number of days after a password has expired (see max_pass_age) during which the password should still be accepted (and user should update her password during the next login).
pass_warn_period => int
The number of days before a password is going to expire (see max_pass_age) during which the user should be warned.
shell* => str
User's home directory.
uid* => int
Numeric user ID.
user* => str
User (login) name.
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
set_user_password(%args) -> [status, msg, result, meta]
Set user's password.
Arguments ('*' denotes required arguments):
backup => bool (default: 0)
Whether to backup when modifying files.
Backup is written with
.bak
extension in the same directory. Unmodified file will not be backed up. Previous backup will be overwritten.etc_dir* => str (default: "/etc")
Specify location of passwd files.
pass => any
user => any
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
user_exists(%args) -> [status, msg, result, meta]
Check whether user exists.
Arguments ('*' denotes required arguments):
etc_dir* => str (default: "/etc")
Specify location of passwd files.
uid* => int
user* => str
Return value:
Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.
AUTHOR
Steven Haryanto <stevenharyanto@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Steven Haryanto.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.