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 | |
21 | class KUserGroup; |
22 | class QString; |
23 | |
24 | #ifdef Q_OS_WIN |
25 | typedef void *K_UID; |
26 | typedef void *K_GID; |
27 | struct WindowsSIDWrapper; |
28 | #else |
29 | #include <sys/types.h> |
30 | typedef uid_t K_UID; |
31 | typedef gid_t K_GID; |
32 | struct passwd; |
33 | struct 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 | */ |
56 | template<typename T> |
57 | struct KCOREADDONS_EXPORT KUserOrGroupId { |
58 | typedef T NativeType; |
59 | |
60 | protected: |
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 | |
72 | public: |
73 | /* Returns true if this object references a valid user/group ID. |
74 | * |
75 | ote 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 | * |
82 | ote 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 | |
97 | private: |
98 | #ifdef Q_OS_WIN |
99 | QExplicitlySharedDataPointer<WindowsSIDWrapper> data; |
100 | #else |
101 | NativeType id; |
102 | #endif |
103 | }; |
104 | |
105 | #ifdef Q_OS_WIN |
106 | template<> |
107 | KUserOrGroupId<void *>::KUserOrGroupId(); |
108 | template<> |
109 | KUserOrGroupId<void *>::~KUserOrGroupId(); |
110 | template<> |
111 | KUserOrGroupId<void *>::KUserOrGroupId(KUserOrGroupId::NativeType nativeId); |
112 | template<> |
113 | KUserOrGroupId<void *>::KUserOrGroupId(const KUserOrGroupId &other); |
114 | template<> |
115 | KUserOrGroupId<void *> &KUserOrGroupId<void *>::operator=(const KUserOrGroupId &other); |
116 | template<> |
117 | bool KUserOrGroupId<void *>::isValid() const; |
118 | template<> |
119 | KUserOrGroupId<void *>::NativeType KUserOrGroupId<void *>::nativeId() const; |
120 | template<> |
121 | QString KUserOrGroupId<void *>::toString() const; |
122 | template<> |
123 | bool KUserOrGroupId<void *>::operator==(const KUserOrGroupId &other) const; |
124 | template<> |
125 | bool KUserOrGroupId<void *>::operator!=(const KUserOrGroupId &other) const; |
126 | #endif |
127 | |
128 | /* A platform independent user ID. |
129 | */ |
130 | struct 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 | * |
148 | ote 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 | */ |
156 | struct 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 | * |
174 | ote 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 |
181 | inline size_t qHash(const KUserId &id, size_t seed = 0) |
182 | { |
183 | return qHash(key: id.nativeId(), seed); |
184 | } |
185 | inline 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) |
191 | KCOREADDONS_EXPORT size_t qHash(const KUserId &id, size_t seed = 0); |
192 | KCOREADDONS_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 | */ |
207 | class KCOREADDONS_EXPORT KUser |
208 | { |
209 | public: |
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 | |
404 | private: |
405 | QExplicitlySharedDataPointer<class KUserPrivate> d; |
406 | }; |
407 | |
408 | Q_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 | */ |
423 | class KCOREADDONS_EXPORT KUserGroup |
424 | { |
425 | public: |
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 | |
560 | private: |
561 | QSharedDataPointer<class KUserGroupPrivate> d; |
562 | }; |
563 | |
564 | Q_DECLARE_TYPEINFO(KUserGroup, Q_RELOCATABLE_TYPE); |
565 | |
566 | #if !defined(Q_OS_WIN) |
567 | // inline UNIX implementation of KUserOrGroupId |
568 | template<typename T> |
569 | inline bool KUserOrGroupId<T>::isValid() const |
570 | { |
571 | return id != NativeType(-1); |
572 | } |
573 | template<typename T> |
574 | inline bool KUserOrGroupId<T>::operator==(const KUserOrGroupId<T> &other) const |
575 | { |
576 | return id == other.id; |
577 | } |
578 | template<typename T> |
579 | inline bool KUserOrGroupId<T>::operator!=(const KUserOrGroupId<T> &other) const |
580 | { |
581 | return id != other.id; |
582 | } |
583 | template<typename T> |
584 | inline typename KUserOrGroupId<T>::NativeType KUserOrGroupId<T>::nativeId() const |
585 | { |
586 | return id; |
587 | } |
588 | template<typename T> |
589 | inline QString KUserOrGroupId<T>::toString() const |
590 | { |
591 | return QString::number(id); |
592 | } |
593 | template<typename T> |
594 | inline KUserOrGroupId<T>::KUserOrGroupId() |
595 | : id(-1) |
596 | { |
597 | } |
598 | template<typename T> |
599 | inline KUserOrGroupId<T>::KUserOrGroupId(KUserOrGroupId<T>::NativeType nativeId) |
600 | : id(nativeId) |
601 | { |
602 | } |
603 | template<typename T> |
604 | inline KUserOrGroupId<T>::KUserOrGroupId(const KUserOrGroupId<T> &other) |
605 | : id(other.id) |
606 | { |
607 | } |
608 | template<typename T> |
609 | inline KUserOrGroupId<T> &KUserOrGroupId<T>::operator=(const KUserOrGroupId<T> &other) |
610 | { |
611 | id = other.id; |
612 | return *this; |
613 | } |
614 | template<typename T> |
615 | inline KUserOrGroupId<T>::~KUserOrGroupId() |
616 | { |
617 | } |
618 | #endif // !defined(Q_OS_WIN) |
619 | |
620 | inline bool KUser::operator!=(const KUser &other) const |
621 | { |
622 | return !operator==(user: other); |
623 | } |
624 | |
625 | inline bool KUserGroup::operator!=(const KUserGroup &other) const |
626 | { |
627 | return !operator==(group: other); |
628 | } |
629 | |
630 | #endif |
631 | |