File indexing completed on 2024-05-12 15:35:02

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 uint qHash(const KUserId &id, uint seed = 0)
0200 {
0201     return qHash(id.nativeId(), seed);
0202 }
0203 inline uint qHash(const KGroupId &id, uint 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 uint qHash(const KUserId &id, uint seed = 0);
0210 KCOREADDONS_EXPORT uint qHash(const KGroupId &id, uint 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 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 0)
0327     /**
0328      * Returns the group id of the user.
0329      * @return the id of the group or -1 if user is invalid
0330      * @deprecated since 5.0 use KUser::groupId()
0331      */
0332     KCOREADDONS_DEPRECATED_VERSION(5, 0, "Use KUser::groupId()")
0333     K_GID gid() const
0334     {
0335         return groupId().nativeId();
0336     }
0337 #endif
0338 
0339     /**
0340      * Checks whether the user is the super user (root).
0341      * @return true if the user is root
0342      */
0343     bool isSuperUser() const;
0344 
0345     /**
0346      * The login name of the user.
0347      * @return the login name of the user or QString() if user is invalid
0348      */
0349     QString loginName() const;
0350 
0351 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 0)
0352     /**
0353      * The full name of the user.
0354      * @return the full name of the user or QString() if user is invalid
0355      * @deprecated Since 5.0, use property(KUser::FullName) instead
0356      */
0357     KCOREADDONS_DEPRECATED_VERSION(5, 0, "Use KUser::property(KUser::FullName).toString()")
0358     QString fullName() const
0359     {
0360         return property(FullName).toString();
0361     }
0362     /**
0363      * Returns the user id of the user.
0364      * @return the id of the user or -1 (UNIX)/ null(Windows) if user is invalid
0365      * @deprecated since 5.0 use KUser::userId()
0366      */
0367     KCOREADDONS_DEPRECATED_VERSION(5, 0, "Use KUser::userId().nativeId()")
0368     K_UID uid() const
0369     {
0370         return userId().nativeId();
0371     }
0372 #endif
0373 
0374     /**
0375      * The path to the user's home directory.
0376      * @return the home directory of the user or QString() if the
0377      *         user is invalid
0378      */
0379     QString homeDir() const;
0380 
0381     /**
0382      * The path to the user's face file.
0383      * @return the path to the user's face file or QString() if no
0384      *         face has been set
0385      */
0386     QString faceIconPath() const;
0387 
0388     /**
0389      * The path to the user's login shell.
0390      * @return the login shell of the user or QString() if the
0391      *         user is invalid
0392      */
0393     QString shell() const;
0394 
0395     /**
0396      * @param maxCount the maximum number of groups to return
0397      * @return all groups of the user
0398      */
0399     QList<KUserGroup> groups(uint maxCount = KCOREADDONS_UINT_MAX) const;
0400 
0401     /**
0402      * @param maxCount the maximum number of groups to return
0403      * @return all group names of the user
0404      */
0405     QStringList groupNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
0406 
0407     enum UserProperty {
0408         FullName,
0409         RoomNumber,
0410         WorkPhone,
0411         HomePhone,
0412     };
0413 
0414     /**
0415      * Returns an extended property.
0416      *
0417      * Under Windows, @p RoomNumber, @p WorkPhone and @p HomePhone are unsupported.
0418      *
0419      * @return a QVariant with the value of the property or an invalid QVariant,
0420      *         if the property is not set
0421      */
0422     QVariant property(UserProperty which) const;
0423 
0424     /**
0425      * Destructor.
0426      */
0427     ~KUser();
0428 
0429     /**
0430      * @param maxCount the maximum number of users to return
0431      * @return all users of the system.
0432      */
0433     static QList<KUser> allUsers(uint maxCount = KCOREADDONS_UINT_MAX);
0434 
0435     /**
0436      * @param maxCount the maximum number of users to return
0437      * @return all user names of the system.
0438      */
0439     static QStringList allUserNames(uint maxCount = KCOREADDONS_UINT_MAX);
0440 
0441 private:
0442     QExplicitlySharedDataPointer<class KUserPrivate> d;
0443 };
0444 
0445 /**
0446  * \class KUserGroup kuser.h <KUserGroup>
0447  *
0448  * @short Represents a group on your system
0449  *
0450  * This class represents a group on your system. You can either get
0451  * information about the group of the current user, of fetch information about
0452  * a group on the system. Instances of this class will be explicitly shared,
0453  * so copying objects is very cheap and you can safely pass objects by value.
0454  *
0455  * @author Jan Schaefer <j_schaef@informatik.uni-kl.de>
0456  */
0457 class KCOREADDONS_EXPORT KUserGroup
0458 {
0459 public:
0460     /**
0461      * Create an object from a group name.
0462      * If the group does not exist, isValid() will return false.
0463      * @param name the name of the group
0464      */
0465     explicit KUserGroup(const QString &name);
0466 
0467     /**
0468      * Create an object from a group name.
0469      * If the group does not exist, isValid() will return false.
0470      * @param name the name of the group
0471      */
0472     explicit KUserGroup(const char *name);
0473 
0474     /**
0475      * Creates an object for the group with the given group id.
0476      * If the KGroupId object is invalid this one will be, too.
0477      * @param gid the group id
0478      */
0479     explicit KUserGroup(KGroupId gid);
0480 
0481     /**
0482      * Create an object from the group of the current user.
0483      * @param mode if #KUser::UseEffectiveUID is passed the effective user
0484      *        will be used. If #KUser::UseRealUserID is passed the real user
0485      *        will be used.
0486      *        The real UID will be different than the effective UID in setuid
0487      *        programs; in  such a case use the effective UID for checking
0488      *        permissions, and the real UID for displaying information about
0489      *        the group associated with the user.
0490      */
0491     explicit KUserGroup(KUser::UIDMode mode = KUser::UseEffectiveUID);
0492 
0493     /**
0494      * Create an object from a group id.
0495      * If the group does not exist, isValid() will return false.
0496      * @param gid the group id
0497      */
0498     explicit KUserGroup(K_GID gid);
0499 
0500 #ifndef Q_OS_WIN
0501     /**
0502      * Creates an object from a group structure.
0503      * If the pointer is null, isValid() will return false.
0504      * @param g the group structure to create the group from.
0505      */
0506     explicit KUserGroup(const group *g);
0507 #endif
0508 
0509     /**
0510      * Creates a new KUserGroup instance from another KUserGroup object
0511      * @param group the KUserGroup to copy
0512      */
0513     KUserGroup(const KUserGroup &group);
0514 
0515     /**
0516      * Copies a group
0517      * @param group the group that should be copied
0518      * @return this group
0519      */
0520     KUserGroup &operator=(const KUserGroup &group);
0521 
0522     /**
0523      * Two KUserGroup objects are equal if their gid()s are identical.
0524      * Invalid groups never compare equal.
0525      * @return true if the groups are identical
0526      */
0527     bool operator==(const KUserGroup &group) const;
0528 
0529     /**
0530      * Two KUserGroup objects are not equal if their gid()s are not identical.
0531      * Invalid groups always compare unequal.
0532      * @return true if the groups are not identical
0533      */
0534     bool operator!=(const KUserGroup &group) const;
0535 
0536     /**
0537      * Returns whether the group is valid.
0538      * A KUserGroup object can be invalid if it is
0539      * created with a non-existing gid or name.
0540      * @return true if the group is valid
0541      */
0542     bool isValid() const;
0543 
0544 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 0)
0545     /**
0546      * Returns the group id of the group.
0547      * @return the group id of the group or -1 if the group is invalid
0548      * @deprecated since 5.0 use KUserGroup::groupId()
0549      */
0550     KCOREADDONS_DEPRECATED_VERSION(5, 0, "Use KUserGroup::groupId().nativeId()")
0551     K_GID gid() const
0552     {
0553         return groupId().nativeId();
0554     }
0555 #endif
0556 
0557     /** @return the native group id of the user. */
0558     KGroupId groupId() const;
0559 
0560     /**
0561      * The name of the group.
0562      * @return the name of the group
0563      */
0564     QString name() const;
0565 
0566     /**
0567      * @param maxCount the maximum number of users to return
0568      * @return a list of all users of the group
0569      */
0570     QList<KUser> users(uint maxCount = KCOREADDONS_UINT_MAX) const;
0571 
0572     /**
0573      * @param maxCount the maximum number of groups to return
0574      * @return a list of all user login names of the group
0575      */
0576     QStringList userNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
0577 
0578     /**
0579      * Destructor.
0580      */
0581     ~KUserGroup();
0582 
0583     /**
0584      * @param maxCount the maximum number of groups to return
0585      * @return a list of all groups on this system
0586      */
0587     static QList<KUserGroup> allGroups(uint maxCount = KCOREADDONS_UINT_MAX);
0588 
0589     /**
0590      * @param maxCount the maximum number of groups to return
0591      * @return a list of all group names on this system
0592      */
0593     static QStringList allGroupNames(uint maxCount = KCOREADDONS_UINT_MAX);
0594 
0595 private:
0596     QSharedDataPointer<class KUserGroupPrivate> d;
0597 };
0598 
0599 #if !defined(Q_OS_WIN)
0600 // inline UNIX implementation of KUserOrGroupId
0601 template<typename T>
0602 inline bool KUserOrGroupId<T>::isValid() const
0603 {
0604     return id != NativeType(-1);
0605 }
0606 template<typename T>
0607 inline bool KUserOrGroupId<T>::operator==(const KUserOrGroupId<T> &other) const
0608 {
0609     return id == other.id;
0610 }
0611 template<typename T>
0612 inline bool KUserOrGroupId<T>::operator!=(const KUserOrGroupId<T> &other) const
0613 {
0614     return id != other.id;
0615 }
0616 template<typename T>
0617 inline typename KUserOrGroupId<T>::NativeType KUserOrGroupId<T>::nativeId() const
0618 {
0619     return id;
0620 }
0621 template<typename T>
0622 inline QString KUserOrGroupId<T>::toString() const
0623 {
0624     return QString::number(id);
0625 }
0626 template<typename T>
0627 inline KUserOrGroupId<T>::KUserOrGroupId()
0628     : id(-1)
0629 {
0630 }
0631 template<typename T>
0632 inline KUserOrGroupId<T>::KUserOrGroupId(KUserOrGroupId<T>::NativeType nativeId)
0633     : id(nativeId)
0634 {
0635 }
0636 template<typename T>
0637 inline KUserOrGroupId<T>::KUserOrGroupId(const KUserOrGroupId<T> &other)
0638     : id(other.id)
0639 {
0640 }
0641 template<typename T>
0642 inline KUserOrGroupId<T> &KUserOrGroupId<T>::operator=(const KUserOrGroupId<T> &other)
0643 {
0644     id = other.id;
0645     return *this;
0646 }
0647 template<typename T>
0648 inline KUserOrGroupId<T>::~KUserOrGroupId()
0649 {
0650 }
0651 #endif // !defined(Q_OS_WIN)
0652 
0653 inline bool KUser::operator!=(const KUser &other) const
0654 {
0655     return !operator==(other);
0656 }
0657 
0658 inline bool KUserGroup::operator!=(const KUserGroup &other) const
0659 {
0660     return !operator==(other);
0661 }
0662 
0663 #endif