2017-11-18 17:09:20 +01:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2015-10-25 22:32:30 +01:00
# pragma once
2018-03-21 15:26:02 +01:00
# include <grp.h>
2018-11-21 18:09:04 +01:00
# if ENABLE_GSHADOW
2018-03-21 15:26:02 +01:00
# include <gshadow.h>
2018-11-21 18:09:04 +01:00
# endif
2018-03-21 15:26:02 +01:00
# include <pwd.h>
# include <shadow.h>
2015-10-25 22:32:30 +01:00
# include <stdbool.h>
2016-08-19 05:19:10 +02:00
# include <stdint.h>
2015-11-18 22:46:33 +01:00
# include <sys/types.h>
2016-04-22 14:10:09 +02:00
# include <unistd.h>
2015-10-25 22:32:30 +01:00
bool uid_is_valid ( uid_t uid ) ;
static inline bool gid_is_valid ( gid_t gid ) {
return uid_is_valid ( ( uid_t ) gid ) ;
}
int parse_uid ( const char * s , uid_t * ret_uid ) ;
2020-01-26 13:51:12 +01:00
int parse_uid_range ( const char * s , uid_t * ret_lower , uid_t * ret_upper ) ;
2015-10-25 22:32:30 +01:00
static inline int parse_gid ( const char * s , gid_t * ret_gid ) {
return parse_uid ( s , ( uid_t * ) ret_gid ) ;
}
char * getlogname_malloc ( void ) ;
char * getusername_malloc ( void ) ;
2018-08-02 18:36:47 +02:00
typedef enum UserCredsFlags {
2018-08-20 16:06:41 +02:00
USER_CREDS_PREFER_NSS = 1 < < 0 , /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */
USER_CREDS_ALLOW_MISSING = 1 < < 1 , /* if a numeric UID string is resolved, be OK if there's no record for it */
USER_CREDS_CLEAN = 1 < < 2 , /* try to clean up shell and home fields with invalid data */
2018-08-02 18:36:47 +02:00
} UserCredsFlags ;
int get_user_creds ( const char * * username , uid_t * uid , gid_t * gid , const char * * home , const char * * shell , UserCredsFlags flags ) ;
int get_group_creds ( const char * * groupname , gid_t * gid , UserCredsFlags flags ) ;
2015-10-25 22:32:30 +01:00
char * uid_to_name ( uid_t uid ) ;
char * gid_to_name ( gid_t gid ) ;
int in_gid ( gid_t gid ) ;
int in_group ( const char * name ) ;
2020-01-08 16:22:29 +01:00
int merge_gid_lists ( const gid_t * list1 , size_t size1 , const gid_t * list2 , size_t size2 , gid_t * * result ) ;
int getgroups_alloc ( gid_t * * gids ) ;
2015-10-25 22:32:30 +01:00
int get_home_dir ( char * * ret ) ;
int get_shell ( char * * _ret ) ;
int reset_uid_gid ( void ) ;
2015-10-26 19:08:09 +01:00
int take_etc_passwd_lock ( const char * root ) ;
2015-10-27 00:42:07 +01:00
# define UID_INVALID ((uid_t) -1)
# define GID_INVALID ((gid_t) -1)
2017-12-04 17:06:56 +01:00
# define UID_NOBODY ((uid_t) 65534U)
# define GID_NOBODY ((gid_t) 65534U)
2018-01-29 14:23:31 +01:00
# define ETC_PASSWD_LOCK_PATH " / etc / .pwd.lock"
2019-08-07 12:34:46 +02:00
static inline bool uid_is_system ( uid_t uid ) {
return uid < = SYSTEM_UID_MAX ;
}
static inline bool gid_is_system ( gid_t gid ) {
return gid < = SYSTEM_GID_MAX ;
}
2016-08-19 05:19:10 +02:00
static inline bool uid_is_dynamic ( uid_t uid ) {
return DYNAMIC_UID_MIN < = uid & & uid < = DYNAMIC_UID_MAX ;
}
2017-12-02 13:07:18 +01:00
static inline bool gid_is_dynamic ( gid_t gid ) {
return uid_is_dynamic ( ( uid_t ) gid ) ;
}
2019-08-07 12:34:46 +02:00
static inline bool uid_is_container ( uid_t uid ) {
return CONTAINER_UID_BASE_MIN < = uid & & uid < = CONTAINER_UID_BASE_MAX ;
2017-12-02 12:59:21 +01:00
}
2019-08-07 12:34:46 +02:00
static inline bool gid_is_container ( gid_t gid ) {
return uid_is_container ( ( uid_t ) gid ) ;
2017-12-02 12:59:21 +01:00
}
2016-08-19 05:19:10 +02:00
/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer
* NULL is special */
2015-10-27 00:42:07 +01:00
# define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
# define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
# define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
# define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
2016-04-22 14:10:09 +02:00
static inline bool userns_supported ( void ) {
return access ( " /proc/self/uid_map " , F_OK ) > = 0 ;
}
2016-07-14 12:23:39 +02:00
2020-04-04 12:23:02 +02:00
typedef enum ValidUserFlags {
VALID_USER_RELAX = 1 < < 0 ,
VALID_USER_WARN = 1 < < 1 ,
VALID_USER_ALLOW_NUMERIC = 1 < < 2 ,
} ValidUserFlags ;
bool valid_user_group_name ( const char * u , ValidUserFlags flags ) ;
2016-07-14 12:23:39 +02:00
bool valid_gecos ( const char * d ) ;
bool valid_home ( const char * p ) ;
2016-09-28 18:37:39 +02:00
2018-01-30 14:28:10 +01:00
static inline bool valid_shell ( const char * p ) {
/* We have the same requirements, so just piggy-back on the home check.
*
* Let ' s ignore / etc / shells because this is only applicable to real and
* not system users . It is also incompatible with the idea of empty / etc .
*/
return valid_home ( p ) ;
}
2016-09-28 18:37:39 +02:00
int maybe_setgroups ( size_t size , const gid_t * list ) ;
2018-01-10 18:26:03 +01:00
bool synthesize_nobody ( void ) ;
2018-03-21 15:26:02 +01:00
int fgetpwent_sane ( FILE * stream , struct passwd * * pw ) ;
int fgetspent_sane ( FILE * stream , struct spwd * * sp ) ;
int fgetgrent_sane ( FILE * stream , struct group * * gr ) ;
int putpwent_sane ( const struct passwd * pw , FILE * stream ) ;
int putspent_sane ( const struct spwd * sp , FILE * stream ) ;
int putgrent_sane ( const struct group * gr , FILE * stream ) ;
2018-06-29 08:54:07 +02:00
# if ENABLE_GSHADOW
2018-03-21 15:26:02 +01:00
int fgetsgent_sane ( FILE * stream , struct sgrp * * sg ) ;
int putsgent_sane ( const struct sgrp * sg , FILE * stream ) ;
# endif
2019-04-23 18:17:04 +02:00
2019-08-07 12:34:29 +02:00
bool is_nologin_shell ( const char * shell ) ;