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 * @internal
56 * @author Alex Richardson <arichardson.kde@gmail.com>
57 */
58template<typename T>
59struct KCOREADDONS_EXPORT KUserOrGroupId {
60 typedef T NativeType;
61
62protected:
63 /** Creates an invalid KUserOrGroupId */
64 KUserOrGroupId();
65 /** Creates a KUserOrGroupId from a native user/group ID. On windows this will not take
66 * ownership over the passed SID, a copy will be created instead.
67 */
68 explicit KUserOrGroupId(NativeType nativeId);
69 /** Copy constructor. This is very fast, objects can be passed by value */
70 KUserOrGroupId(const KUserOrGroupId<T> &other);
71 KUserOrGroupId &operator=(const KUserOrGroupId<T> &other);
72 ~KUserOrGroupId();
73
74public:
75 /** @return true if this object references a valid user/group ID.
76 * @note If this returns true it doesn't necessarily mean that the referenced user/group exists,
77 * it only checks whether this value could be a valid user/group ID.
78 */
79 bool isValid() const;
80 /**
81 * @return A user/group ID that can be used in operating system specific functions
82 * @note 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 /** @return 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 /** @return whether this KUserOrGroupId is equal to @p other */
93 bool operator==(const KUserOrGroupId &other) const;
94 /** @return whether this KUserOrGroupId is not equal to @p 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 * @see KUserOrGroupId
130 * @since 5.0
131 * @author Alex Richardson <arichardson.kde@gmail.com>
132 */
133struct KCOREADDONS_EXPORT KUserId : public KUserOrGroupId<K_UID> {
134 /** Creates an invalid KUserId */
135 KUserId()
136 {
137 }
138 /** Creates an KUserId from the native user ID type */
139 explicit KUserId(K_UID uid)
140 : KUserOrGroupId(uid)
141 {
142 }
143 KUserId(const KUserId &other)
144 : KUserOrGroupId(other)
145 {
146 }
147 ~KUserId()
148 {
149 }
150 /** @return a KUserId for the user with name @p name, or an invalid KUserId if no
151 * user with this name was found on the system
152 */
153 static KUserId fromName(const QString &name);
154 /** @return a KUserId for the current user. This is like ::getuid() on UNIX. */
155 static KUserId currentUserId();
156 /** @return a KUserId for the current effective user. This is like ::geteuid() on UNIX.
157 * @note Windows does not have setuid binaries, so on Windows this will always be the same
158 * as KUserId::currentUserId()
159 */
160 static KUserId currentEffectiveUserId();
161};
162
163/** A platform independent group ID.
164 * @see KUserOrGroupId
165 * @since 5.0
166 * @author Alex Richardson <arichardson.kde@gmail.com>
167 */
168struct KCOREADDONS_EXPORT KGroupId : public KUserOrGroupId<K_GID> {
169 /** Creates an invalid KGroupId */
170 KGroupId()
171 {
172 }
173 /** Creates an KGroupId from the native group ID type */
174 explicit KGroupId(K_GID gid)
175 : KUserOrGroupId(gid)
176 {
177 }
178 KGroupId(const KGroupId &other)
179 : KUserOrGroupId(other)
180 {
181 }
182 ~KGroupId()
183 {
184 }
185 /** @return A KGroupId for the user with name @p name, or an invalid KGroupId if no
186 * user with this name was found on the system
187 */
188 static KGroupId fromName(const QString &name);
189 /** @return a KGroupId for the current user. This is like ::getgid() on UNIX. */
190 static KGroupId currentGroupId();
191 /** @return a KGroupId for the current effective user. This is like ::getegid() on UNIX.
192 * @note Windows does not have setuid binaries, so on Windows this will always be the same
193 * as KGroupId::currentGroupId()
194 */
195 static KGroupId currentEffectiveGroupId();
196};
197
198#ifndef Q_OS_WIN
199inline uint qHash(const KUserId &id, uint seed = 0)
200{
201 return qHash(id.nativeId(), seed);
202}
203inline uint qHash(const KGroupId &id, uint seed = 0)
204{
205 return qHash(id.nativeId(), seed);
206}
207#else
208// can't be inline on windows, because we would need to include windows.h (which can break code)
209KCOREADDONS_EXPORT uint qHash(const KUserId &id, uint seed = 0);
210KCOREADDONS_EXPORT uint qHash(const KGroupId &id, uint seed = 0);
211#endif
212
213/**
214 * \class KUser kuser.h <KUser>
215 *
216 * @short Represents a user on your system
217 *
218 * This class represents a user on your system. You can either get
219 * information about the current user, or fetch information about
220 * a user on the system. Instances of this class will be explicitly shared,
221 * so copying objects is very cheap and you can safely pass objects by value.
222 *
223 * @author Tim Jansen <tim@tjansen.de>
224 */
225class KCOREADDONS_EXPORT KUser
226{
227public:
228 enum UIDMode {
229 UseEffectiveUID, ///< Use the effective user id.
230 UseRealUserID, ///< Use the real user id.
231 };
232
233 /**
234 * Creates an object that contains information about the current user.
235 * (as returned by getuid(2) or geteuid(2), taking $LOGNAME/$USER into
236 * account).
237 * @param mode if #UseEffectiveUID is passed the effective
238 * user is returned.
239 * If #UseRealUserID is passed the real user will be
240 * returned.
241 * The real UID will be different than the effective UID in setuid
242 * programs; in
243 * such a case use the effective UID for checking permissions, and
244 * the real UID for displaying information about the user.
245 */
246 explicit KUser(UIDMode mode = UseEffectiveUID);
247
248 /**
249 * Creates an object for the user with the given user id.
250 * If the user does not exist isValid() will return false.
251 * @param uid the user id
252 */
253 explicit KUser(K_UID uid);
254
255 /**
256 * Creates an object for the user with the given user id.
257 * If the KUserId object is invalid this one will be, too.
258 * @param uid the user id
259 */
260 explicit KUser(KUserId uid);
261
262 /**
263 * Creates an object that contains information about the user with the given
264 * name. If the user does not exist isValid() will return false.
265 *
266 * @param name the name of the user
267 */
268 explicit KUser(const QString &name);
269
270 /**
271 * Creates an object that contains information about the user with the given
272 * name. If the user does not exist isValid() will return false.
273 *
274 * @param name the name of the user
275 */
276 explicit KUser(const char *name);
277
278#ifndef Q_OS_WIN
279 /**
280 * Creates an object from a passwd structure.
281 * If the pointer is null isValid() will return false.
282 *
283 * @param p the passwd structure to create the user from
284 */
285 explicit KUser(const passwd *p);
286#endif
287
288 /**
289 * Creates an object from another KUser object
290 * @param user the user to create the new object from
291 */
292 KUser(const KUser &user);
293
294 /**
295 * Copies a user
296 * @param user the user to copy
297 * @return this object
298 */
299 KUser &operator=(const KUser &user);
300
301 /**
302 * Two KUser objects are equal if the userId() are identical.
303 * Invalid users never compare equal.
304 */
305 bool operator==(const KUser &user) const;
306
307 /**
308 * Two KUser objects are not equal if userId() are not identical.
309 * Invalid users always compare unequal.
310 */
311 bool operator!=(const KUser &user) const;
312
313 /**
314 * Returns true if the user is valid. A KUser object can be invalid if
315 * you created it with an non-existing uid or name.
316 * @return true if the user is valid
317 */
318 bool isValid() const;
319
320 /** @return the native user id of the user. */
321 KUserId userId() const;
322
323 /** @return the native user id of the user. */
324 KGroupId groupId() const;
325
326 /**
327 * Checks whether the user is the super user (root).
328 * @return true if the user is root
329 */
330 bool isSuperUser() const;
331
332 /**
333 * The login name of the user.
334 * @return the login name of the user or QString() if user is invalid
335 */
336 QString loginName() const;
337
338 /**
339 * The path to the user's home directory.
340 * @return the home directory of the user or QString() if the
341 * user is invalid
342 */
343 QString homeDir() const;
344
345 /**
346 * The path to the user's face file.
347 * @return the path to the user's face file or QString() if no
348 * face has been set
349 */
350 QString faceIconPath() const;
351
352 /**
353 * The path to the user's login shell.
354 * @return the login shell of the user or QString() if the
355 * user is invalid
356 */
357 QString shell() const;
358
359 /**
360 * @param maxCount the maximum number of groups to return
361 * @return all groups of the user
362 */
363 QList<KUserGroup> groups(uint maxCount = KCOREADDONS_UINT_MAX) const;
364
365 /**
366 * @param maxCount the maximum number of groups to return
367 * @return all group names of the user
368 */
369 QStringList groupNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
370
371 enum UserProperty {
372 FullName,
373 RoomNumber,
374 WorkPhone,
375 HomePhone,
376 };
377
378 /**
379 * Returns an extended property.
380 *
381 * Under Windows, @p RoomNumber, @p WorkPhone and @p HomePhone are unsupported.
382 *
383 * @return 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 /**
389 * Destructor.
390 */
391 ~KUser();
392
393 /**
394 * @param maxCount the maximum number of users to return
395 * @return all users of the system.
396 */
397 static QList<KUser> allUsers(uint maxCount = KCOREADDONS_UINT_MAX);
398
399 /**
400 * @param maxCount the maximum number of users to return
401 * @return all user names of the system.
402 */
403 static QStringList allUserNames(uint maxCount = KCOREADDONS_UINT_MAX);
404
405private:
406 QExplicitlySharedDataPointer<class KUserPrivate> d;
407};
408
409Q_DECLARE_TYPEINFO(KUser, Q_RELOCATABLE_TYPE);
410
411/**
412 * \class KUserGroup kuser.h <KUserGroup>
413 *
414 * @short Represents a group on your system
415 *
416 * This class represents a group on your system. You can either get
417 * information about the group of the current user, of fetch information about
418 * a group on the system. Instances of this class will be explicitly shared,
419 * so copying objects is very cheap and you can safely pass objects by value.
420 *
421 * @author Jan Schaefer <j_schaef@informatik.uni-kl.de>
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 * @param name the name of the group
430 */
431 explicit KUserGroup(const QString &name);
432
433 /**
434 * Create an object from a group name.
435 * If the group does not exist, isValid() will return false.
436 * @param name the name of the group
437 */
438 explicit KUserGroup(const char *name);
439
440 /**
441 * Creates an object for the group with the given group id.
442 * If the KGroupId object is invalid this one will be, too.
443 * @param gid the group id
444 */
445 explicit KUserGroup(KGroupId gid);
446
447 /**
448 * Create an object from the group of the current user.
449 * @param mode if #KUser::UseEffectiveUID is passed the effective user
450 * will be used. If #KUser::UseRealUserID is passed the real user
451 * will be used.
452 * The real UID will be different than the effective UID in setuid
453 * programs; in such a case use the effective UID for checking
454 * permissions, and the real UID for displaying information about
455 * the group associated with the user.
456 */
457 explicit KUserGroup(KUser::UIDMode mode = KUser::UseEffectiveUID);
458
459 /**
460 * Create an object from a group id.
461 * If the group does not exist, isValid() will return false.
462 * @param gid the group id
463 */
464 explicit KUserGroup(K_GID gid);
465
466#ifndef Q_OS_WIN
467 /**
468 * Creates an object from a group structure.
469 * If the pointer is null, isValid() will return false.
470 * @param g the group structure to create the group from.
471 */
472 explicit KUserGroup(const group *g);
473#endif
474
475 /**
476 * Creates a new KUserGroup instance from another KUserGroup object
477 * @param group the KUserGroup to copy
478 */
479 KUserGroup(const KUserGroup &group);
480
481 /**
482 * Copies a group
483 * @param group the group that should be copied
484 * @return this group
485 */
486 KUserGroup &operator=(const KUserGroup &group);
487
488 /**
489 * Two KUserGroup objects are equal if their gid()s are identical.
490 * Invalid groups never compare equal.
491 * @return true if the groups are identical
492 */
493 bool operator==(const KUserGroup &group) const;
494
495 /**
496 * Two KUserGroup objects are not equal if their gid()s are not identical.
497 * Invalid groups always compare unequal.
498 * @return true if the groups are not identical
499 */
500 bool operator!=(const KUserGroup &group) const;
501
502 /**
503 * Returns whether the group is valid.
504 * A KUserGroup object can be invalid if it is
505 * created with a non-existing gid or name.
506 * @return true if the group is valid
507 */
508 bool isValid() const;
509
510 /** @return the native group id of the user. */
511 KGroupId groupId() const;
512
513 /**
514 * The name of the group.
515 * @return the name of the group
516 */
517 QString name() const;
518
519 /**
520 * @param maxCount the maximum number of users to return
521 * @return a list of all users of the group
522 */
523 QList<KUser> users(uint maxCount = KCOREADDONS_UINT_MAX) const;
524
525 /**
526 * @param maxCount the maximum number of groups to return
527 * @return a list of all user login names of the group
528 */
529 QStringList userNames(uint maxCount = KCOREADDONS_UINT_MAX) const;
530
531 /**
532 * Destructor.
533 */
534 ~KUserGroup();
535
536 /**
537 * @param maxCount the maximum number of groups to return
538 * @return a list of all groups on this system
539 */
540 static QList<KUserGroup> allGroups(uint maxCount = KCOREADDONS_UINT_MAX);
541
542 /**
543 * @param maxCount the maximum number of groups to return
544 * @return a list of all group names on this system
545 */
546 static QStringList allGroupNames(uint maxCount = KCOREADDONS_UINT_MAX);
547
548private:
549 QSharedDataPointer<class KUserGroupPrivate> d;
550};
551
552Q_DECLARE_TYPEINFO(KUserGroup, Q_RELOCATABLE_TYPE);
553
554#if !defined(Q_OS_WIN)
555// inline UNIX implementation of KUserOrGroupId
556template<typename T>
557inline bool KUserOrGroupId<T>::isValid() const
558{
559 return id != NativeType(-1);
560}
561template<typename T>
562inline bool KUserOrGroupId<T>::operator==(const KUserOrGroupId<T> &other) const
563{
564 return id == other.id;
565}
566template<typename T>
567inline bool KUserOrGroupId<T>::operator!=(const KUserOrGroupId<T> &other) const
568{
569 return id != other.id;
570}
571template<typename T>
572inline typename KUserOrGroupId<T>::NativeType KUserOrGroupId<T>::nativeId() const
573{
574 return id;
575}
576template<typename T>
577inline QString KUserOrGroupId<T>::toString() const
578{
579 return QString::number(id);
580}
581template<typename T>
582inline KUserOrGroupId<T>::KUserOrGroupId()
583 : id(-1)
584{
585}
586template<typename T>
587inline KUserOrGroupId<T>::KUserOrGroupId(KUserOrGroupId<T>::NativeType nativeId)
588 : id(nativeId)
589{
590}
591template<typename T>
592inline KUserOrGroupId<T>::KUserOrGroupId(const KUserOrGroupId<T> &other)
593 : id(other.id)
594{
595}
596template<typename T>
597inline KUserOrGroupId<T> &KUserOrGroupId<T>::operator=(const KUserOrGroupId<T> &other)
598{
599 id = other.id;
600 return *this;
601}
602template<typename T>
603inline KUserOrGroupId<T>::~KUserOrGroupId()
604{
605}
606#endif // !defined(Q_OS_WIN)
607
608inline bool KUser::operator!=(const KUser &other) const
609{
610 return !operator==(user: other);
611}
612
613inline bool KUserGroup::operator!=(const KUserGroup &other) const
614{
615 return !operator==(group: other);
616}
617
618#endif
619

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