View source with raw comments or as raw
   1/*  Part of SWI-Prolog
   2
   3    Author:        Jan Wielemaker
   4    E-mail:        J.Wielemaker@vu.nl
   5    WWW:           http://www.swi-prolog.org
   6    Copyright (c)  2011-2013, VU University Amsterdam
   7    All rights reserved.
   8
   9    Redistribution and use in source and binary forms, with or without
  10    modification, are permitted provided that the following conditions
  11    are met:
  12
  13    1. Redistributions of source code must retain the above copyright
  14       notice, this list of conditions and the following disclaimer.
  15
  16    2. Redistributions in binary form must reproduce the above copyright
  17       notice, this list of conditions and the following disclaimer in
  18       the documentation and/or other materials provided with the
  19       distribution.
  20
  21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32    POSSIBILITY OF SUCH DAMAGE.
  33*/
  34
  35:- module(uid,
  36          [ getuid/1,                   % -UID
  37            getgid/1,                   % -GID
  38            geteuid/1,                  % -UID
  39            getegid/1,                  % -GID
  40            getgroups/1,                % -GIDs
  41            user_info/2,                % +User, -UserInfo
  42            group_info/2,               % +Group, -GroupInfo
  43            user_data/3,                % +Field, +UserInfo, -Value
  44            group_data/3,               % +Field, +GroupInfo, -Value
  45            setuid/1,                   % +UID
  46            setgid/1,                   % +GID
  47            seteuid/1,                  % +UID
  48            setegid/1,                  % +GID
  49
  50            set_user_and_group/1,       % +User
  51            set_user_and_group/2        % +User, +Group
  52          ]).
  53
  54:- use_foreign_library(foreign(uid)).
  55
  56:- if(predicate_property(initgroups(_,_), defined)).
  57:- export(initgroups/2).
  58:- else.
  59initgroups(_,_).
  60:- endif.
  61
  62:- if(predicate_property(setgroups(_), defined)).
  63:- export(setgroups/1).
  64:- endif.
  65
  66/** <module> User and group management on Unix systems
  67
  68This module provides and interface  to   user  and  group information on
  69Posix systems. In addition, it allows for   changing user and group ids.
  70When changing user and group settings for   the calling process, bear in
  71mind that:
  72
  73  - Changing user and groups of the calling process requires permission.
  74  - The functions setgroups() and initgroups() are not part of the
  75    POSIX standard and therefore the derived predicates may not be
  76    present.
  77
  78@see    Please check the documentation of your OS for details on the
  79        semantics of this predicates.
  80*/
  81
  82%!  getuid(-UID) is det.
  83%
  84%   UID is the real user ID of the calling process.
  85
  86%!  getgid(-GID) is det.
  87%
  88%   GID is the real group ID of the calling process.
  89
  90%!  geteuid(-UID) is det.
  91%
  92%   UID is the effective user ID of the calling process.
  93
  94%!  getegid(-GID) is det.
  95%
  96%   GID is the effective group ID of the calling process.
  97
  98%!  getgroups(-GroupsIDs:list(integer)) is det.
  99%
 100%   GroupsIDs is the set of supplementary   group IDs of the calling
 101%   process.  Note  that  these   are    numeric   identifiers.  Use
 102%   group_info/2  to  obtain  details   on    the   returned   group
 103%   identifiers.
 104
 105%!  user_info(+User, -UserData) is det.
 106%
 107%   UserData represent the passwd  information   for  User.  User is
 108%   either a numeric UID or a   user name. The predicate user_data/3
 109%   can be used to extract information from UserData.
 110
 111%!  user_data(?Field, ?UserData, ?Value)
 112%
 113%   Value is the value for Field in UserData.  Defined fields are:
 114%
 115%     * name
 116%     Name of the user
 117%     * password
 118%     Password hash of the user (or =x= if this is not accessible)
 119%     * uid
 120%     Numeric user id of the user
 121%     * gid
 122%     Numeric primary group id of the user
 123%     * comment
 124%     The _gecos_ field
 125%     * home
 126%     Home directory of the user
 127%     * shell
 128%     Default (login) shell of the user.
 129
 130user_data(name,     user_info(Nam, _, _, _, _, _, _), Nam).
 131user_data(password, user_info(_, PWD, _, _, _, _, _), PWD).
 132user_data(uid,      user_info(_, _, UID, _, _, _, _), UID).
 133user_data(gid,      user_info(_, _, _, GID, _, _, _), GID).
 134user_data(comment,  user_info(_, _, _, _, GEC, _, _), GEC).
 135user_data(home,     user_info(_, _, _, _, _, HOM, _), HOM).
 136user_data(shell,    user_info(_, _, _, _, _, _, SHE), SHE).
 137
 138%!  group_info(+Group, -GroupData) is det.
 139%
 140%   GroupData represent the group information   for  Group. Group is
 141%   either a numeric GID or a group name. The predicate group_data/3
 142%   can be used to extract information from GroupData.
 143
 144%!  group_data(?Field, ?GroupData, ?Value)
 145%
 146%   Value is the value for Field  GroupData.  Defined fields are:
 147%
 148%     * name
 149%     Name of the user
 150%     * password
 151%     Password hash of the user (or =x= if this is not accessible)
 152%     * gid
 153%     Numeric group id of the group
 154%     * members
 155%     List of user-names that are member of this group.
 156
 157group_data(name,     group_info(Nam, _, _, _), Nam).
 158group_data(password, group_info(_, PWD, _, _), PWD).
 159group_data(gid,      group_info(_, _, GID, _), GID).
 160group_data(members,  group_info(_, _, _, MBR), MBR).
 161
 162                 /*******************************
 163                 *             SETTING          *
 164                 *******************************/
 165
 166%!  setuid(+UID)
 167%
 168%   Set the user id of the calling process.
 169
 170%!  seteuid(+UID)
 171%
 172%   Set the effective user id of the calling process.
 173
 174
 175%!  setgid(+GID)
 176%
 177%   Set the group id of the calling process.
 178
 179%!  setegid(+GID)
 180%
 181%   Set the effective group id of the calling process.
 182
 183%!  initgroups(+User, +Group) is det.
 184%
 185%   Initialise the group access list of   the calling process to the
 186%   registered groups for User and the   group Group. This predicate
 187%   is only available if the underlying OS provides it.
 188
 189%!  setgroups(+Groups:list(integer)) is det.
 190%
 191%   Set the group access list of the caling process to the indicated
 192%   groups. This predicate is only available   if  the underlying OS
 193%   provides it.
 194
 195%!  set_user_and_group(+User) is det.
 196%!  set_user_and_group(+User, +Group) is det.
 197%
 198%   Set the UID and GID to the User. User  is either a UID or a user
 199%   name. If Group is not specified, the   primary  group of User is
 200%   used. If initgroups/2 is available,   the resulting group access
 201%   list of the calling process consists   of  the registered groups
 202%   for User and the specified Group.
 203
 204set_user_and_group(User) :-
 205    user_info(User, Data),
 206    user_data(uid, Data, UID),
 207    user_data(gid, Data, GID),
 208    initgroups(User, GID),
 209    setgid(GID),
 210    setuid(UID).
 211
 212set_user_and_group(User, Group) :-
 213    user_info(User, Data),
 214    group_info(Group, GData),
 215    user_data(uid, Data, UID),
 216    user_data(gid, Data, UGID),
 217    group_data(gid, GData, GID),
 218    initgroups(User, UGID),
 219    setgid(GID),
 220    setuid(UID).