1/*
2 KUser - represent a user/account
3
4 SPDX-FileCopyrightText: 2002-2003 Tim Jansen <tim@tjansen.de>
5 SPDX-FileCopyrightText: 2003 Oswald Buddenhagen <ossi@kde.org>
6 SPDX-FileCopyrightText: 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
7 SPDX-FileCopyrightText: 2014 Alex Richardson <arichardson.kde@gmail.com>
8
9 SPDX-License-Identifier: LGPL-2.0-or-later
10*/
11#ifndef KUSER_H
12#define KUSER_H
13
14#include <kcoreaddons_export.h>
15
16#include <QSharedDataPointer>
17#include <QStringList>
18#include <QVariant>
19#include <qcontainerfwd.h>
20
21class KUserGroup;
22class QString;
23
24#ifdef Q_OS_WIN
25typedef void *K_UID;
26typedef void *K_GID;
27struct WindowsSIDWrapper;
28#else
29#include <sys/types.h>
30typedef uid_t K_UID;
31typedef gid_t K_GID;
32struct passwd;
33struct group;
34#endif
35
36// The following is to avoid compile errors using msvc, and it is done
37// using a common #define to avoid helpful people accidentally cleaning this
38// not quite pretty thing and breaking it for people on windows.
39// See https://git.reviewboard.kde.org/r/127598/ for details
40#define KCOREADDONS_UINT_MAX (std::numeric_limits<uint>::max)()
41
42/* A platform independent user or group ID.
43 *
44 *
45 * This struct is required since Windows does not have an integer uid_t/gid_t type
46 * but instead uses an opaque binary blob (SID) which must free allocated memory.
47 * On UNIX this is simply a uid_t/gid_t and all operations are inline, so there is
48 * no runtime overhead over using the uid_t/gid_t directly. On Windows this is an implicitly
49 * shared class that frees the underlying SID once no more references remain.
50 *
51 * Unlike KUser/KUserGroup this does not query additional information, it is simply
52 * an abstraction over the native user/group ID type. If more information is necessary, a
53 * KUser or KUserGroup instance can be constructed from this ID
54 *
55 */
56template<typename T>
57struct KCOREADDONS_EXPORT KUserOrGroupId {
58 typedef T NativeType;
59
60protected:
61 /* Creates an invalid KUserOrGroupId */
62 KUserOrGroupId();
63 /* Creates a KUserOrGroupId from a native user/group ID. On windows this will not take
64 * ownership over the passed SID, a copy will be created instead.
65 */
66 explicit KUserOrGroupId(NativeType nativeId);
67 /* Copy constructor. This is very fast, objects can be passed by value */
68 KUserOrGroupId(const KUserOrGroupId<T> &other);
69 KUserOrGroupId &operator=(const KUserOrGroupId<T> &other);
70 ~KUserOrGroupId();
71
72public:
73 /* Returns true if this object references a valid user/group ID.
74 *
75ote If this returns true it doesn't necessarily mean that the referenced user/group exists,
76 * it only checks whether this value could be a valid user/group ID.
77 */
78 bool isValid() const;
79 /*
80 * Returns A user/group ID that can be used in operating system specific functions
81 *
82ote On Windows the returned pointer will be freed once the last KUserOrGroupId referencing
83 * this user/group ID is deleted. Make sure that the KUserOrGroupId object remains valid as
84 * long as the native pointer is needed.
85 */
86 NativeType nativeId() const;
87 /* Returns A string representation of this user ID, not the name of the user
88 * On UNIX this is a simple integer, e.g. "0" for root. On Windows this is a string
89 * like e.g. "S-1-5-32-544" for the Administrators group
90 */
91 QString toString() const;
92 /* Returns whether this KUserOrGroupId is equal to \a other */
93 bool operator==(const KUserOrGroupId &other) const;
94 /* Returns whether this KUserOrGroupId is not equal to \a other */
95 bool operator!=(const KUserOrGroupId &other) const;
96
97private:
98#ifdef Q_OS_WIN
99 QExplicitlySharedDataPointer<WindowsSIDWrapper> data;
100#else
101 NativeType id;
102#endif
103};
104
105#ifdef Q_OS_WIN
106template<>
107KUserOrGroupId<void *>::KUserOrGroupId();
108template<>
109KUserOrGroupId<void *>::~KUserOrGroupId();
110template<>
111KUserOrGroupId<void *>::KUserOrGroupId(KUserOrGroupId::NativeType nativeId);
112template<>
113KUserOrGroupId<void *>::KUserOrGroupId(const KUserOrGroupId &other);
114template<>
115KUserOrGroupId<void *> &KUserOrGroupId<void *>::operator=(const KUserOrGroupId &other);
116template<>
117bool KUserOrGroupId<void *>::isValid() const;
118template<>
119KUserOrGroupId<void *>::NativeType KUserOrGroupId<void *>::nativeId() const;
120template<>
121QString KUserOrGroupId<void *>::toString() const;
122template<>
123bool KUserOrGroupId<void *>::operator==(const KUserOrGroupId &other) const;
124template<>
125bool KUserOrGroupId<void *>::operator!=(const KUserOrGroupId &other) const;
126#endif
127
128/* A platform independent user ID.
129 */
130struct KCOREADDONS_EXPORT KUserId : public KUserOrGroupId<K_UID> {
131 /* Creates an invalid KUserId */
132 KUserId()
133 {
134 }
135 /* Creates an KUserId from the native user ID type */
136 explicit KUserId(K_UID uid)
137 : KUserOrGroupId(uid)
138 {
139 }
140 /* Returns a KUserId for the user with name \a name, or an invalid KUserId if no
141 * user with this name was found on the system
142 */
143 static KUserId fromName(const QString &name);
144 /* Returns a KUserId for the current user. This is like ::getuid() on UNIX. */
145 static KUserId currentUserId();
146 /* Returns a KUserId for the current effective user. This is like ::geteuid() on UNIX.
147 *
148ote Windows does not have setuid binaries, so on Windows this will always be the same
149 * as KUserId::currentUserId()
150 */
151 static KUserId currentEffectiveUserId();
152};
153
154/* A platform independent group ID.
155 */
156struct KCOREADDONS_EXPORT KGroupId : public KUserOrGroupId<K_GID> {
157 /* Creates an invalid KGroupId */
158 KGroupId()
159 {
160 }
161 /* Creates an KGroupId from the native group ID type */
162 explicit KGroupId(K_GID gid)
163 : KUserOrGroupId(gid)
164 {
165 }
166 /* Returns A KGroupId for the user with name \a name, or an invalid KGroupId if no
167 * user with this name was found on the system
168 */
169 static KGroupId fromName(const QString &name);
170 /* Returns a KGroupId for the current user. This is like ::getgid() on UNIX. */
171 static KGroupId currentGroupId();
172 /* Returns a KGroupId for the current effective user. This is like ::getegid() on UNIX.
173 *
174ote Windows does not have setuid binaries, so on Windows this will always be the same
175 * as KGroupId::currentGroupId()
176 */
177 static KGroupId currentEffectiveGroupId();
178};
179
180#ifndef Q_OS_WIN
181inline size_t qHash(const KUserId &id, size_t seed = 0)
182{
183 return qHash(key: id.nativeId(), seed);
184}
185inline size_t qHash(const KGroupId &id, size_t seed = 0)
186{
187 return qHash(key: id.nativeId(), seed);
188}
189#else
190// can't be inline on windows, because we would need to include windows.h (which can break code)
191KCOREADDONS_EXPORT size_t qHash(const KUserId &id, size_t seed = 0);
192KCOREADDONS_EXPORT size_t qHash(const KGroupId &id, size_t seed = 0);
193#endif
194
195/*!
196 * \class KUser
197 * \inmodule KCoreAddons
198 *
199 * \brief Represents a user on your system.
200 *
201 * This class represents a user on your system. You can either get
202 * information about the current user, or fetch information about
203 * a user on the system. Instances of this class will be explicitly shared,
204 * so copying objects is very cheap and you can safely pass objects by value.
205 *
206 */
207class KCOREADDONS_EXPORT KUser
208{
209public:
210 /*!
211 * \value UseEffectiveUID Use the effective user id
212 * \value UseRealUserID Use the real user id
213 */
214 enum UIDMode {
215 UseEffectiveUID,
216 UseRealUserID,
217 };
218
219 /*!
220 * Creates an object that contains information about the current user.
221 * (as returned by getuid(2) or geteuid(2), taking $LOGNAME/$USER into
222 * account).
223 *
224 * \a mode if #UseEffectiveUID is passed the effective
225 * user is returned.
226 * If #UseRealUserID is passed the real user will be
227 * returned.
228 * The real UID will be different than the effective UID in setuid
229 * programs; in
230 * such a case use the effective UID for checking permissions, and
231 * the real UID for displaying information about the user.
232 */
233 explicit KUser(UIDMode mode = UseEffectiveUID);
234
235 /*!
236 * Creates an object for the user with the given user id.
237 * If the user does not exist isValid() will return false.
238 *
239 * \a uid the user id
240 */
241 explicit KUser(K_UID uid);
242
243 /*!
244 * Creates an object for the user with the given user id.
245 * If the KUserId object is invalid this one will be, too.
246 *
247 * \a uid the user id
248 */
249 explicit KUser(KUserId uid);
250
251 /*!
252 * Creates an object that contains information about the user with the given
253 * name. If the user does not exist isValid() will return false.
254 *
255 * \a name the name of the user
256 */
257 explicit KUser(const QString &name);
258
259 /*!
260 * Creates an object that contains information about the user with the given
261 * name. If the user does not exist isValid() will return false.
262 *
263 * \a name the name of the user
264 */
265 explicit KUser(const char *name);
266
267#ifndef Q_OS_WIN
268 /*!
269 * Creates an object from a passwd structure.
270 * If the pointer is null isValid() will return false.
271 *
272 * \a p the passwd structure to create the user from
273 */
274 explicit KUser(const passwd *p);
275#endif
276
277 /*!
278 * Creates an object from another KUser object
279 *
280 * \a user the user to create the new object from
281 */
282 KUser(const KUser &user);
283
284 /*!
285 * Copies a user
286 *
287 * \a user the user to copy
288 *
289 * Returns this object
290 */
291 KUser &operator=(const KUser &user);
292
293 /*!
294 * Two KUser objects are equal if the userId() are identical.
295 * Invalid users never compare equal.
296 */
297 bool operator==(const KUser &user) const;
298
299 /*!
300 * Two KUser objects are not equal if userId() are not identical.
301 * Invalid users always compare unequal.
302 */
303 bool operator!=(const KUser &user) const;
304
305 /*!
306 * Returns true if the user is valid. A KUser object can be invalid if
307 * you created it with an non-existing uid or name.
308 * Returns true if the user is valid
309 */
310 bool isValid() const;
311
312 /*! Returns the native user id of the user. */
313 KUserId userId() const;
314
315 /*! Returns the native user id of the user. */
316 KGroupId groupId() const;
317
318 /*!
319 * Checks whether the user is the super user (root).
320 * Returns true if the user is root
321 */
322 bool isSuperUser() const;
323
324 /*!
325 * The login name of the user.
326 * Returns the login name of the user or QString() if user is invalid
327 */
328 QString loginName() const;
329
330 /*!
331 * The path to the user's home directory.
332 * Returns the home directory of the user or QString() if the
333 * user is invalid
334 */
335 QString homeDir() const;
336
337 /*!
338 * The path to the user's face file.
339 * Returns the path to the user's face file or QString() if no
340 * face has been set
341 */
342 QString faceIconPath() const;
343
344 /*!
345 * The path to the user's login shell.
346 * Returns the login shell of the user or QString() if the
347 * user is invalid
348 */
349 QString shell() const;
350
351 /*!
352 * \a maxCount the maximum number of groups to return
353 *
354 * Returns all groups of the user
355 */
356 QList<KUserGroup> groups(uint maxCount = KCOREADDONS_UINT_MAX) const;
357
358 /*!
359 * \a maxCount the maximum number of groups to return
360 *
361 * Returns all group names of the user
362 */
363 QStringList groupNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
364
365 /*!
366 * \value FullName
367 * \value RoomNumber
368 * \value WorkPhone
369 * \value HomePhone
370 */
371 enum UserProperty {
372 FullName,
373 RoomNumber,
374 WorkPhone,
375 HomePhone,
376 };
377
378 /*!
379 * Returns an extended property given by \a which.
380 *
381 * Under Windows, RoomNumber, WorkPhone and HomePhone are unsupported.
382 *
383 * Returns a QVariant with the value of the property or an invalid QVariant,
384 * if the property is not set
385 */
386 QVariant property(UserProperty which) const;
387
388 ~KUser();
389
390 /*!
391 * \a maxCount the maximum number of users to return
392 *
393 * Returns all users of the system.
394 */
395 static QList<KUser> allUsers(uint maxCount = KCOREADDONS_UINT_MAX);
396
397 /*!
398 * \a maxCount the maximum number of users to return
399 *
400 * Returns all user names of the system.
401 */
402 static QStringList allUserNames(uint maxCount = KCOREADDONS_UINT_MAX);
403
404private:
405 QExplicitlySharedDataPointer<class KUserPrivate> d;
406};
407
408Q_DECLARE_TYPEINFO(KUser, Q_RELOCATABLE_TYPE);
409
410/*!
411 * \class KUserGroup
412 * \inheaderfile KUser
413 * \inmodule KCoreAddons
414 *
415 * \brief Represents a group on your system.
416 *
417 * This class represents a group on your system. You can either get
418 * information about the group of the current user, of fetch information about
419 * a group on the system. Instances of this class will be explicitly shared,
420 * so copying objects is very cheap and you can safely pass objects by value.
421 *
422 */
423class KCOREADDONS_EXPORT KUserGroup
424{
425public:
426 /*!
427 * Create an object from a group name.
428 * If the group does not exist, isValid() will return false.
429 *
430 * \a name the name of the group
431 */
432 explicit KUserGroup(const QString &name);
433
434 /*!
435 * Create an object from a group name.
436 * If the group does not exist, isValid() will return false.
437 *
438 * \a name the name of the group
439 */
440 explicit KUserGroup(const char *name);
441
442 /*!
443 * Creates an object for the group with the given group id.
444 * If the KGroupId object is invalid this one will be, too.
445 *
446 * \a gid the group id
447 */
448 explicit KUserGroup(KGroupId gid);
449
450 /*!
451 * Create an object from the group of the current user.
452 *
453 * \a mode if #KUser::UseEffectiveUID is passed the effective user
454 * will be used. If #KUser::UseRealUserID is passed the real user
455 * will be used.
456 * The real UID will be different than the effective UID in setuid
457 * programs; in such a case use the effective UID for checking
458 * permissions, and the real UID for displaying information about
459 * the group associated with the user.
460 */
461 explicit KUserGroup(KUser::UIDMode mode = KUser::UseEffectiveUID);
462
463 /*!
464 * Create an object from a group id.
465 * If the group does not exist, isValid() will return false.
466 *
467 * \a gid the group id
468 */
469 explicit KUserGroup(K_GID gid);
470
471#ifndef Q_OS_WIN
472 /*!
473 * Creates an object from a group structure.
474 * If the pointer is null, isValid() will return false.
475 *
476 * \a g the group structure to create the group from.
477 */
478 explicit KUserGroup(const group *g);
479#endif
480
481 /*!
482 * Creates a new KUserGroup instance from another KUserGroup object
483 *
484 * \a group the KUserGroup to copy
485 */
486 KUserGroup(const KUserGroup &group);
487
488 /*!
489 * Copies a group
490 *
491 * \a group the group that should be copied
492 *
493 * Returns this group
494 */
495 KUserGroup &operator=(const KUserGroup &group);
496
497 /*!
498 * Returns true if this group's gid() is identical to the one from \a group.
499 * Invalid groups never compare equal.
500 */
501 bool operator==(const KUserGroup &group) const;
502
503 /*!
504 * Two KUserGroup objects are not equal if their gid()s are not identical.
505 * Invalid groups always compare unequal.
506 * Returns true if the groups are not identical
507 */
508 bool operator!=(const KUserGroup &group) const;
509
510 /*!
511 * Returns whether the group is valid.
512 * A KUserGroup object can be invalid if it is
513 * created with a non-existing gid or name.
514 * Returns true if the group is valid
515 */
516 bool isValid() const;
517
518 /*! Returns the native group id of the user. */
519 KGroupId groupId() const;
520
521 /*!
522 * The name of the group.
523 * Returns the name of the group
524 */
525 QString name() const;
526
527 /*!
528 * \a maxCount the maximum number of users to return
529 *
530 * Returns a list of all users of the group
531 */
532 QList<KUser> users(uint maxCount = KCOREADDONS_UINT_MAX) const;
533
534 /*!
535 * \a maxCount the maximum number of groups to return
536 *
537 * Returns a list of all user login names of the group
538 */
539 QStringList userNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
540
541 /*!
542 * Destructor.
543 */
544 ~KUserGroup();
545
546 /*!
547 * \a maxCount the maximum number of groups to return
548 *
549 * Returns a list of all groups on this system
550 */
551 static QList<KUserGroup> allGroups(uint maxCount = KCOREADDONS_UINT_MAX);
552
553 /*!
554 * \a maxCount the maximum number of groups to return
555 *
556 * Returns a list of all group names on this system
557 */
558 static QStringList allGroupNames(uint maxCount = KCOREADDONS_UINT_MAX);
559
560private:
561 QSharedDataPointer<class KUserGroupPrivate> d;
562};
563
564Q_DECLARE_TYPEINFO(KUserGroup, Q_RELOCATABLE_TYPE);
565
566#if !defined(Q_OS_WIN)
567// inline UNIX implementation of KUserOrGroupId
568template<typename T>
569inline bool KUserOrGroupId<T>::isValid() const
570{
571 return id != NativeType(-1);
572}
573template<typename T>
574inline bool KUserOrGroupId<T>::operator==(const KUserOrGroupId<T> &other) const
575{
576 return id == other.id;
577}
578template<typename T>
579inline bool KUserOrGroupId<T>::operator!=(const KUserOrGroupId<T> &other) const
580{
581 return id != other.id;
582}
583template<typename T>
584inline typename KUserOrGroupId<T>::NativeType KUserOrGroupId<T>::nativeId() const
585{
586 return id;
587}
588template<typename T>
589inline QString KUserOrGroupId<T>::toString() const
590{
591 return QString::number(id);
592}
593template<typename T>
594inline KUserOrGroupId<T>::KUserOrGroupId()
595 : id(-1)
596{
597}
598template<typename T>
599inline KUserOrGroupId<T>::KUserOrGroupId(KUserOrGroupId<T>::NativeType nativeId)
600 : id(nativeId)
601{
602}
603template<typename T>
604inline KUserOrGroupId<T>::KUserOrGroupId(const KUserOrGroupId<T> &other)
605 : id(other.id)
606{
607}
608template<typename T>
609inline KUserOrGroupId<T> &KUserOrGroupId<T>::operator=(const KUserOrGroupId<T> &other)
610{
611 id = other.id;
612 return *this;
613}
614template<typename T>
615inline KUserOrGroupId<T>::~KUserOrGroupId()
616{
617}
618#endif // !defined(Q_OS_WIN)
619
620inline bool KUser::operator!=(const KUser &other) const
621{
622 return !operator==(user: other);
623}
624
625inline bool KUserGroup::operator!=(const KUserGroup &other) const
626{
627 return !operator==(group: other);
628}
629
630#endif
631

source code of kcoreaddons/src/lib/util/kuser.h