File indexing completed on 2024-04-28 03:53:51

0001 /*
0002     KUser - represent a user/account
0003 
0004     SPDX-FileCopyrightText: 2002-2003 Tim Jansen <tim@tjansen.de>
0005     SPDX-FileCopyrightText: 2003 Oswald Buddenhagen <ossi@kde.org>
0006     SPDX-FileCopyrightText: 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
0007     SPDX-FileCopyrightText: 2014 Alex Richardson <arichardson.kde@gmail.com>
0008 
0009     SPDX-License-Identifier: LGPL-2.0-or-later
0010 */
0011 #ifndef KUSER_H
0012 #define KUSER_H
0013 
0014 #include <kcoreaddons_export.h>
0015 
0016 #include <QSharedDataPointer>
0017 #include <QStringList>
0018 #include <QVariant>
0019 #include <qcontainerfwd.h>
0020 
0021 class KUserGroup;
0022 class QString;
0023 
0024 #ifdef Q_OS_WIN
0025 typedef void *K_UID;
0026 typedef void *K_GID;
0027 struct WindowsSIDWrapper;
0028 #else
0029 #include <sys/types.h>
0030 typedef uid_t K_UID;
0031 typedef gid_t K_GID;
0032 struct passwd;
0033 struct group;
0034 #endif
0035 
0036 // The following is to avoid compile errors using msvc, and it is done
0037 // using a common #define to avoid helpful people accidentally cleaning this
0038 // not quite pretty thing and breaking it for people on windows.
0039 // See https://git.reviewboard.kde.org/r/127598/ for details
0040 #define KCOREADDONS_UINT_MAX (std::numeric_limits<uint>::max)()
0041 
0042 /** A platform independent user or group ID.
0043  *
0044  *
0045  * This struct is required since Windows does not have an integer uid_t/gid_t type
0046  * but instead uses an opaque binary blob (SID) which must free allocated memory.
0047  * On UNIX this is simply a uid_t/gid_t and all operations are inline, so there is
0048  * no runtime overhead over using the uid_t/gid_t directly. On Windows this is an implicitly
0049  * shared class that frees the underlying SID once no more references remain.
0050  *
0051  * Unlike KUser/KUserGroup this does not query additional information, it is simply
0052  * an abstraction over the native user/group ID type. If more information is necessary, a
0053  * KUser or KUserGroup instance can be constructed from this ID
0054  *
0055  * @internal
0056  * @author Alex Richardson <arichardson.kde@gmail.com>
0057  */
0058 template<typename T>
0059 struct KCOREADDONS_EXPORT KUserOrGroupId {
0060     typedef T NativeType;
0061 
0062 protected:
0063     /** Creates an invalid KUserOrGroupId */
0064     KUserOrGroupId();
0065     /** Creates a KUserOrGroupId from a native user/group ID. On windows this will not take
0066      * ownership over the passed SID, a copy will be created instead.
0067      */
0068     explicit KUserOrGroupId(NativeType nativeId);
0069     /** Copy constructor. This is very fast, objects can be passed by value */
0070     KUserOrGroupId(const KUserOrGroupId<T> &other);
0071     KUserOrGroupId &operator=(const KUserOrGroupId<T> &other);
0072     ~KUserOrGroupId();
0073 
0074 public:
0075     /** @return true if this object references a valid user/group ID.
0076      * @note If this returns true it doesn't necessarily mean that the referenced user/group exists,
0077      * it only checks whether this value could be a valid user/group ID.
0078      */
0079     bool isValid() const;
0080     /**
0081      * @return A user/group ID that can be used in operating system specific functions
0082      * @note On Windows the returned pointer will be freed once the last KUserOrGroupId referencing
0083      * this user/group ID is deleted. Make sure that the KUserOrGroupId object remains valid as
0084      * long as the native pointer is needed.
0085      */
0086     NativeType nativeId() const;
0087     /** @return A string representation of this user ID, not the name of the user
0088      * On UNIX this is a simple integer, e.g. "0" for root. On Windows this is a string
0089      * like e.g. "S-1-5-32-544" for the Administrators group
0090      */
0091     QString toString() const;
0092     /** @return whether this KUserOrGroupId is equal to @p other */
0093     bool operator==(const KUserOrGroupId &other) const;
0094     /** @return whether this KUserOrGroupId is not equal to @p other */
0095     bool operator!=(const KUserOrGroupId &other) const;
0096 
0097 private:
0098 #ifdef Q_OS_WIN
0099     QExplicitlySharedDataPointer<WindowsSIDWrapper> data;
0100 #else
0101     NativeType id;
0102 #endif
0103 };
0104 
0105 #ifdef Q_OS_WIN
0106 template<>
0107 KUserOrGroupId<void *>::KUserOrGroupId();
0108 template<>
0109 KUserOrGroupId<void *>::~KUserOrGroupId();
0110 template<>
0111 KUserOrGroupId<void *>::KUserOrGroupId(KUserOrGroupId::NativeType nativeId);
0112 template<>
0113 KUserOrGroupId<void *>::KUserOrGroupId(const KUserOrGroupId &other);
0114 template<>
0115 KUserOrGroupId<void *> &KUserOrGroupId<void *>::operator=(const KUserOrGroupId &other);
0116 template<>
0117 bool KUserOrGroupId<void *>::isValid() const;
0118 template<>
0119 KUserOrGroupId<void *>::NativeType KUserOrGroupId<void *>::nativeId() const;
0120 template<>
0121 QString KUserOrGroupId<void *>::toString() const;
0122 template<>
0123 bool KUserOrGroupId<void *>::operator==(const KUserOrGroupId &other) const;
0124 template<>
0125 bool KUserOrGroupId<void *>::operator!=(const KUserOrGroupId &other) const;
0126 #endif
0127 
0128 /** A platform independent user ID.
0129  * @see KUserOrGroupId
0130  * @since 5.0
0131  * @author Alex Richardson <arichardson.kde@gmail.com>
0132  */
0133 struct KCOREADDONS_EXPORT KUserId : public KUserOrGroupId<K_UID> {
0134     /** Creates an invalid KUserId */
0135     KUserId()
0136     {
0137     }
0138     /** Creates an KUserId from the native user ID type */
0139     explicit KUserId(K_UID uid)
0140         : KUserOrGroupId(uid)
0141     {
0142     }
0143     KUserId(const KUserId &other)
0144         : KUserOrGroupId(other)
0145     {
0146     }
0147     ~KUserId()
0148     {
0149     }
0150     /** @return a KUserId for the user with name @p name, or an invalid KUserId if no
0151      * user with this name was found on the system
0152      */
0153     static KUserId fromName(const QString &name);
0154     /** @return a KUserId for the current user. This is like ::getuid() on UNIX. */
0155     static KUserId currentUserId();
0156     /** @return a KUserId for the current effective user. This is like ::geteuid() on UNIX.
0157      * @note Windows does not have setuid binaries, so on Windows this will always be the same
0158      * as KUserId::currentUserId()
0159      */
0160     static KUserId currentEffectiveUserId();
0161 };
0162 
0163 /** A platform independent group ID.
0164  * @see KUserOrGroupId
0165  * @since 5.0
0166  * @author Alex Richardson <arichardson.kde@gmail.com>
0167  */
0168 struct KCOREADDONS_EXPORT KGroupId : public KUserOrGroupId<K_GID> {
0169     /** Creates an invalid KGroupId */
0170     KGroupId()
0171     {
0172     }
0173     /** Creates an KGroupId from the native group ID type */
0174     explicit KGroupId(K_GID gid)
0175         : KUserOrGroupId(gid)
0176     {
0177     }
0178     KGroupId(const KGroupId &other)
0179         : KUserOrGroupId(other)
0180     {
0181     }
0182     ~KGroupId()
0183     {
0184     }
0185     /** @return A KGroupId for the user with name @p name, or an invalid KGroupId if no
0186      * user with this name was found on the system
0187      */
0188     static KGroupId fromName(const QString &name);
0189     /** @return a KGroupId for the current user. This is like ::getgid() on UNIX. */
0190     static KGroupId currentGroupId();
0191     /** @return a KGroupId for the current effective user. This is like ::getegid() on UNIX.
0192      * @note Windows does not have setuid binaries, so on Windows this will always be the same
0193      * as KGroupId::currentGroupId()
0194      */
0195     static KGroupId currentEffectiveGroupId();
0196 };
0197 
0198 #ifndef Q_OS_WIN
0199 inline size_t qHash(const KUserId &id, size_t seed = 0)
0200 {
0201     return qHash(id.nativeId(), seed);
0202 }
0203 inline size_t qHash(const KGroupId &id, size_t seed = 0)
0204 {
0205     return qHash(id.nativeId(), seed);
0206 }
0207 #else
0208 // can't be inline on windows, because we would need to include windows.h (which can break code)
0209 KCOREADDONS_EXPORT size_t qHash(const KUserId &id, size_t seed = 0);
0210 KCOREADDONS_EXPORT size_t qHash(const KGroupId &id, size_t seed = 0);
0211 #endif
0212 
0213 /**
0214  * \class KUser kuser.h <KUser>
0215  *
0216  * @short Represents a user on your system
0217  *
0218  * This class represents a user on your system. You can either get
0219  * information about the current user, or fetch information about
0220  * a user on the system. Instances of this class will be explicitly shared,
0221  * so copying objects is very cheap and you can safely pass objects by value.
0222  *
0223  * @author Tim Jansen <tim@tjansen.de>
0224  */
0225 class KCOREADDONS_EXPORT KUser
0226 {
0227 public:
0228     enum UIDMode {
0229         UseEffectiveUID, ///< Use the effective user id.
0230         UseRealUserID, ///< Use the real user id.
0231     };
0232 
0233     /**
0234      * Creates an object that contains information about the current user.
0235      * (as returned by getuid(2) or geteuid(2), taking $LOGNAME/$USER into
0236      * account).
0237      * @param mode if #UseEffectiveUID is passed the effective
0238      *             user is returned.
0239      *        If #UseRealUserID is passed the real user will be
0240      *        returned.
0241      *        The real UID will be different than the effective UID in setuid
0242      *        programs; in
0243      *        such a case use the effective UID for checking permissions, and
0244      *        the real UID for displaying information about the user.
0245      */
0246     explicit KUser(UIDMode mode = UseEffectiveUID);
0247 
0248     /**
0249      * Creates an object for the user with the given user id.
0250      * If the user does not exist isValid() will return false.
0251      * @param uid the user id
0252      */
0253     explicit KUser(K_UID uid);
0254 
0255     /**
0256      * Creates an object for the user with the given user id.
0257      * If the KUserId object is invalid this one will be, too.
0258      * @param uid the user id
0259      */
0260     explicit KUser(KUserId uid);
0261 
0262     /**
0263      * Creates an object that contains information about the user with the given
0264      * name. If the user does not exist isValid() will return false.
0265      *
0266      * @param name the name of the user
0267      */
0268     explicit KUser(const QString &name);
0269 
0270     /**
0271      * Creates an object that contains information about the user with the given
0272      * name. If the user does not exist isValid() will return false.
0273      *
0274      * @param name the name of the user
0275      */
0276     explicit KUser(const char *name);
0277 
0278 #ifndef Q_OS_WIN
0279     /**
0280      * Creates an object from a passwd structure.
0281      * If the pointer is null isValid() will return false.
0282      *
0283      * @param p the passwd structure to create the user from
0284      */
0285     explicit KUser(const passwd *p);
0286 #endif
0287 
0288     /**
0289      * Creates an object from another KUser object
0290      * @param user the user to create the new object from
0291      */
0292     KUser(const KUser &user);
0293 
0294     /**
0295      * Copies a user
0296      * @param user the user to copy
0297      * @return this object
0298      */
0299     KUser &operator=(const KUser &user);
0300 
0301     /**
0302      * Two KUser objects are equal if the userId() are identical.
0303      * Invalid users never compare equal.
0304      */
0305     bool operator==(const KUser &user) const;
0306 
0307     /**
0308      * Two KUser objects are not equal if userId() are not identical.
0309      * Invalid users always compare unequal.
0310      */
0311     bool operator!=(const KUser &user) const;
0312 
0313     /**
0314      * Returns true if the user is valid. A KUser object can be invalid if
0315      * you created it with an non-existing uid or name.
0316      * @return true if the user is valid
0317      */
0318     bool isValid() const;
0319 
0320     /** @return the native user id of the user. */
0321     KUserId userId() const;
0322 
0323     /** @return the native user id of the user. */
0324     KGroupId groupId() const;
0325 
0326     /**
0327      * Checks whether the user is the super user (root).
0328      * @return true if the user is root
0329      */
0330     bool isSuperUser() const;
0331 
0332     /**
0333      * The login name of the user.
0334      * @return the login name of the user or QString() if user is invalid
0335      */
0336     QString loginName() const;
0337 
0338     /**
0339      * The path to the user's home directory.
0340      * @return the home directory of the user or QString() if the
0341      *         user is invalid
0342      */
0343     QString homeDir() const;
0344 
0345     /**
0346      * The path to the user's face file.
0347      * @return the path to the user's face file or QString() if no
0348      *         face has been set
0349      */
0350     QString faceIconPath() const;
0351 
0352     /**
0353      * The path to the user's login shell.
0354      * @return the login shell of the user or QString() if the
0355      *         user is invalid
0356      */
0357     QString shell() const;
0358 
0359     /**
0360      * @param maxCount the maximum number of groups to return
0361      * @return all groups of the user
0362      */
0363     QList<KUserGroup> groups(uint maxCount = KCOREADDONS_UINT_MAX) const;
0364 
0365     /**
0366      * @param maxCount the maximum number of groups to return
0367      * @return all group names of the user
0368      */
0369     QStringList groupNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
0370 
0371     enum UserProperty {
0372         FullName,
0373         RoomNumber,
0374         WorkPhone,
0375         HomePhone,
0376     };
0377 
0378     /**
0379      * Returns an extended property.
0380      *
0381      * Under Windows, @p RoomNumber, @p WorkPhone and @p HomePhone are unsupported.
0382      *
0383      * @return a QVariant with the value of the property or an invalid QVariant,
0384      *         if the property is not set
0385      */
0386     QVariant property(UserProperty which) const;
0387 
0388     /**
0389      * Destructor.
0390      */
0391     ~KUser();
0392 
0393     /**
0394      * @param maxCount the maximum number of users to return
0395      * @return all users of the system.
0396      */
0397     static QList<KUser> allUsers(uint maxCount = KCOREADDONS_UINT_MAX);
0398 
0399     /**
0400      * @param maxCount the maximum number of users to return
0401      * @return all user names of the system.
0402      */
0403     static QStringList allUserNames(uint maxCount = KCOREADDONS_UINT_MAX);
0404 
0405 private:
0406     QExplicitlySharedDataPointer<class KUserPrivate> d;
0407 };
0408 
0409 Q_DECLARE_TYPEINFO(KUser, Q_RELOCATABLE_TYPE);
0410 
0411 /**
0412  * \class KUserGroup kuser.h <KUserGroup>
0413  *
0414  * @short Represents a group on your system
0415  *
0416  * This class represents a group on your system. You can either get
0417  * information about the group of the current user, of fetch information about
0418  * a group on the system. Instances of this class will be explicitly shared,
0419  * so copying objects is very cheap and you can safely pass objects by value.
0420  *
0421  * @author Jan Schaefer <j_schaef@informatik.uni-kl.de>
0422  */
0423 class KCOREADDONS_EXPORT KUserGroup
0424 {
0425 public:
0426     /**
0427      * Create an object from a group name.
0428      * If the group does not exist, isValid() will return false.
0429      * @param name the name of the group
0430      */
0431     explicit KUserGroup(const QString &name);
0432 
0433     /**
0434      * Create an object from a group name.
0435      * If the group does not exist, isValid() will return false.
0436      * @param name the name of the group
0437      */
0438     explicit KUserGroup(const char *name);
0439 
0440     /**
0441      * Creates an object for the group with the given group id.
0442      * If the KGroupId object is invalid this one will be, too.
0443      * @param gid the group id
0444      */
0445     explicit KUserGroup(KGroupId gid);
0446 
0447     /**
0448      * Create an object from the group of the current user.
0449      * @param mode if #KUser::UseEffectiveUID is passed the effective user
0450      *        will be used. If #KUser::UseRealUserID is passed the real user
0451      *        will be used.
0452      *        The real UID will be different than the effective UID in setuid
0453      *        programs; in  such a case use the effective UID for checking
0454      *        permissions, and the real UID for displaying information about
0455      *        the group associated with the user.
0456      */
0457     explicit KUserGroup(KUser::UIDMode mode = KUser::UseEffectiveUID);
0458 
0459     /**
0460      * Create an object from a group id.
0461      * If the group does not exist, isValid() will return false.
0462      * @param gid the group id
0463      */
0464     explicit KUserGroup(K_GID gid);
0465 
0466 #ifndef Q_OS_WIN
0467     /**
0468      * Creates an object from a group structure.
0469      * If the pointer is null, isValid() will return false.
0470      * @param g the group structure to create the group from.
0471      */
0472     explicit KUserGroup(const group *g);
0473 #endif
0474 
0475     /**
0476      * Creates a new KUserGroup instance from another KUserGroup object
0477      * @param group the KUserGroup to copy
0478      */
0479     KUserGroup(const KUserGroup &group);
0480 
0481     /**
0482      * Copies a group
0483      * @param group the group that should be copied
0484      * @return this group
0485      */
0486     KUserGroup &operator=(const KUserGroup &group);
0487 
0488     /**
0489      * Two KUserGroup objects are equal if their gid()s are identical.
0490      * Invalid groups never compare equal.
0491      * @return true if the groups are identical
0492      */
0493     bool operator==(const KUserGroup &group) const;
0494 
0495     /**
0496      * Two KUserGroup objects are not equal if their gid()s are not identical.
0497      * Invalid groups always compare unequal.
0498      * @return true if the groups are not identical
0499      */
0500     bool operator!=(const KUserGroup &group) const;
0501 
0502     /**
0503      * Returns whether the group is valid.
0504      * A KUserGroup object can be invalid if it is
0505      * created with a non-existing gid or name.
0506      * @return true if the group is valid
0507      */
0508     bool isValid() const;
0509 
0510     /** @return the native group id of the user. */
0511     KGroupId groupId() const;
0512 
0513     /**
0514      * The name of the group.
0515      * @return the name of the group
0516      */
0517     QString name() const;
0518 
0519     /**
0520      * @param maxCount the maximum number of users to return
0521      * @return a list of all users of the group
0522      */
0523     QList<KUser> users(uint maxCount = KCOREADDONS_UINT_MAX) const;
0524 
0525     /**
0526      * @param maxCount the maximum number of groups to return
0527      * @return a list of all user login names of the group
0528      */
0529     QStringList userNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
0530 
0531     /**
0532      * Destructor.
0533      */
0534     ~KUserGroup();
0535 
0536     /**
0537      * @param maxCount the maximum number of groups to return
0538      * @return a list of all groups on this system
0539      */
0540     static QList<KUserGroup> allGroups(uint maxCount = KCOREADDONS_UINT_MAX);
0541 
0542     /**
0543      * @param maxCount the maximum number of groups to return
0544      * @return a list of all group names on this system
0545      */
0546     static QStringList allGroupNames(uint maxCount = KCOREADDONS_UINT_MAX);
0547 
0548 private:
0549     QSharedDataPointer<class KUserGroupPrivate> d;
0550 };
0551 
0552 Q_DECLARE_TYPEINFO(KUserGroup, Q_RELOCATABLE_TYPE);
0553 
0554 #if !defined(Q_OS_WIN)
0555 // inline UNIX implementation of KUserOrGroupId
0556 template<typename T>
0557 inline bool KUserOrGroupId<T>::isValid() const
0558 {
0559     return id != NativeType(-1);
0560 }
0561 template<typename T>
0562 inline bool KUserOrGroupId<T>::operator==(const KUserOrGroupId<T> &other) const
0563 {
0564     return id == other.id;
0565 }
0566 template<typename T>
0567 inline bool KUserOrGroupId<T>::operator!=(const KUserOrGroupId<T> &other) const
0568 {
0569     return id != other.id;
0570 }
0571 template<typename T>
0572 inline typename KUserOrGroupId<T>::NativeType KUserOrGroupId<T>::nativeId() const
0573 {
0574     return id;
0575 }
0576 template<typename T>
0577 inline QString KUserOrGroupId<T>::toString() const
0578 {
0579     return QString::number(id);
0580 }
0581 template<typename T>
0582 inline KUserOrGroupId<T>::KUserOrGroupId()
0583     : id(-1)
0584 {
0585 }
0586 template<typename T>
0587 inline KUserOrGroupId<T>::KUserOrGroupId(KUserOrGroupId<T>::NativeType nativeId)
0588     : id(nativeId)
0589 {
0590 }
0591 template<typename T>
0592 inline KUserOrGroupId<T>::KUserOrGroupId(const KUserOrGroupId<T> &other)
0593     : id(other.id)
0594 {
0595 }
0596 template<typename T>
0597 inline KUserOrGroupId<T> &KUserOrGroupId<T>::operator=(const KUserOrGroupId<T> &other)
0598 {
0599     id = other.id;
0600     return *this;
0601 }
0602 template<typename T>
0603 inline KUserOrGroupId<T>::~KUserOrGroupId()
0604 {
0605 }
0606 #endif // !defined(Q_OS_WIN)
0607 
0608 inline bool KUser::operator!=(const KUser &other) const
0609 {
0610     return !operator==(other);
0611 }
0612 
0613 inline bool KUserGroup::operator!=(const KUserGroup &other) const
0614 {
0615     return !operator==(other);
0616 }
0617 
0618 #endif