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 | * @internal |
56 | * @author Alex Richardson <arichardson.kde@gmail.com> |
57 | */ |
58 | template<typename T> |
59 | struct KCOREADDONS_EXPORT KUserOrGroupId { |
60 | typedef T NativeType; |
61 | |
62 | protected: |
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 | |
74 | public: |
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 | |
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 | * @see KUserOrGroupId |
130 | * @since 5.0 |
131 | * @author Alex Richardson <arichardson.kde@gmail.com> |
132 | */ |
133 | struct 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 | */ |
168 | struct 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 |
199 | inline size_t qHash(const KUserId &id, size_t seed = 0) |
200 | { |
201 | return qHash(key: id.nativeId(), seed); |
202 | } |
203 | inline size_t qHash(const KGroupId &id, size_t seed = 0) |
204 | { |
205 | return qHash(key: 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) |
209 | KCOREADDONS_EXPORT size_t qHash(const KUserId &id, size_t seed = 0); |
210 | KCOREADDONS_EXPORT size_t qHash(const KGroupId &id, size_t 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 | */ |
225 | class KCOREADDONS_EXPORT KUser |
226 | { |
227 | public: |
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 | |
405 | private: |
406 | QExplicitlySharedDataPointer<class KUserPrivate> d; |
407 | }; |
408 | |
409 | Q_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 | */ |
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 | * @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 | |
548 | private: |
549 | QSharedDataPointer<class KUserGroupPrivate> d; |
550 | }; |
551 | |
552 | Q_DECLARE_TYPEINFO(KUserGroup, Q_RELOCATABLE_TYPE); |
553 | |
554 | #if !defined(Q_OS_WIN) |
555 | // inline UNIX implementation of KUserOrGroupId |
556 | template<typename T> |
557 | inline bool KUserOrGroupId<T>::isValid() const |
558 | { |
559 | return id != NativeType(-1); |
560 | } |
561 | template<typename T> |
562 | inline bool KUserOrGroupId<T>::operator==(const KUserOrGroupId<T> &other) const |
563 | { |
564 | return id == other.id; |
565 | } |
566 | template<typename T> |
567 | inline bool KUserOrGroupId<T>::operator!=(const KUserOrGroupId<T> &other) const |
568 | { |
569 | return id != other.id; |
570 | } |
571 | template<typename T> |
572 | inline typename KUserOrGroupId<T>::NativeType KUserOrGroupId<T>::nativeId() const |
573 | { |
574 | return id; |
575 | } |
576 | template<typename T> |
577 | inline QString KUserOrGroupId<T>::toString() const |
578 | { |
579 | return QString::number(id); |
580 | } |
581 | template<typename T> |
582 | inline KUserOrGroupId<T>::KUserOrGroupId() |
583 | : id(-1) |
584 | { |
585 | } |
586 | template<typename T> |
587 | inline KUserOrGroupId<T>::KUserOrGroupId(KUserOrGroupId<T>::NativeType nativeId) |
588 | : id(nativeId) |
589 | { |
590 | } |
591 | template<typename T> |
592 | inline KUserOrGroupId<T>::KUserOrGroupId(const KUserOrGroupId<T> &other) |
593 | : id(other.id) |
594 | { |
595 | } |
596 | template<typename T> |
597 | inline KUserOrGroupId<T> &KUserOrGroupId<T>::operator=(const KUserOrGroupId<T> &other) |
598 | { |
599 | id = other.id; |
600 | return *this; |
601 | } |
602 | template<typename T> |
603 | inline KUserOrGroupId<T>::~KUserOrGroupId() |
604 | { |
605 | } |
606 | #endif // !defined(Q_OS_WIN) |
607 | |
608 | inline bool KUser::operator!=(const KUser &other) const |
609 | { |
610 | return !operator==(user: other); |
611 | } |
612 | |
613 | inline bool KUserGroup::operator!=(const KUserGroup &other) const |
614 | { |
615 | return !operator==(group: other); |
616 | } |
617 | |
618 | #endif |
619 | |