diff options
| author | Sam Varshavchik | 2022-03-06 14:01:22 -0500 |
|---|---|---|
| committer | Sam Varshavchik | 2022-03-06 14:01:22 -0500 |
| commit | de8102845637c813e411fd0ca1f545497358b109 (patch) | |
| tree | eba05f611c3c51731348c16eb12c4b502d13393b | |
| parent | a219cd3c45aa2545a7a641acb277acb5e8be87f9 (diff) | |
| download | courier-libs-de8102845637c813e411fd0ca1f545497358b109.tar.bz2 | |
Implement libmail_getuid() and libmail_getgid().
Based on a patch by Ondřej Surý <ondrej@sury.org>.
| -rw-r--r-- | numlib/changeuidgid.c | 115 | ||||
| -rw-r--r-- | numlib/numlib.h | 3 |
2 files changed, 105 insertions, 13 deletions
diff --git a/numlib/changeuidgid.c b/numlib/changeuidgid.c index adaee40..ce69839 100644 --- a/numlib/changeuidgid.c +++ b/numlib/changeuidgid.c @@ -47,16 +47,21 @@ void libmail_changeuidgid(uid_t uid, gid_t gid) } } -void libmail_changeusername(const char *uname, const gid_t *forcegrp) +/** + * Obtain the uid associated to uname and, optionally, the user primary gid + */ +uid_t libmail_getuid(const char *uname, gid_t *pw_gid) { -struct passwd *pw; -uid_t changeuid; -gid_t changegid; + size_t bufsize; + char *buf; + struct passwd pwbuf; + struct passwd *pw; -/* uname might be a pointer returned from a previous called to getpw(), -** and libc has a problem getting it back. -*/ -char *p=malloc(strlen(uname)+1); + /* + ** uname might be a pointer returned from a previous called to getpw(), + ** and libc has a problem getting it back. + */ + char *p=malloc(strlen(uname)+1); if (!p) { @@ -65,8 +70,29 @@ char *p=malloc(strlen(uname)+1); } strcpy(p, uname); +#ifdef _SC_GETGR_R_SIZE_MAX + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize == -1) /* Value was indeterminate */ + { +#endif + bufsize = 16384; /* Should be more than enough */ + } + + buf = malloc(bufsize); + if (buf == NULL) + { + perror("malloc"); + exit(1); + } + + errno=ENOENT; - if ((pw=getpwnam(p)) == 0) + + getpwnam_r(p, &pwbuf, buf, bufsize, &pw); + + free(buf); + + if (pw == 0) { free(p); perror("getpwnam"); @@ -74,11 +100,19 @@ char *p=malloc(strlen(uname)+1); } free(p); - changeuid=pw->pw_uid; + if ( pw_gid ) *pw_gid = pw->pw_gid; + + return pw->pw_uid; +} + +void libmail_changeusername(const char *uname, const gid_t *forcegrp) +{ +uid_t changeuid; +gid_t changegid; - if ( !forcegrp ) forcegrp= &pw->pw_gid; + changeuid=libmail_getuid(uname, &changegid); - changegid= *forcegrp; + if ( forcegrp ) changegid= *forcegrp; if ( setgid( changegid )) { @@ -87,7 +121,7 @@ char *p=malloc(strlen(uname)+1); } #if HAVE_INITGROUPS - if ( getuid() == 0 && initgroups(pw->pw_name, changegid) ) + if ( getuid() == 0 && initgroups(uname, changegid) ) { perror("initgroups"); exit(1); @@ -108,3 +142,58 @@ char *p=malloc(strlen(uname)+1); exit(1); } } + +gid_t libmail_getgid(const char *gname) +{ + gid_t g; + struct group grp; + struct group *result; + char *buf; + size_t bufsize; + int s; + char *p=malloc(strlen(gname)+1); + + if (!p) + { + perror("malloc"); + exit(1); + } + strcpy(p, gname); + +#ifdef _SC_GETGR_R_SIZE_MAX + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize == -1) /* Value was indeterminate */ +#endif + { + bufsize = 16384; /* Should be more than enough */ + } + + buf = malloc(bufsize); + if (buf == NULL) + { + perror("malloc"); + exit(1); + } + + s = getgrnam_r(p, &grp, buf, bufsize, &result); + free(p); + + if (result == NULL) + { + if (s == 0) + { + fprintf(stderr, "CRIT: Group %s not found\n", gname); + } + else + { + errno = s; + perror("getpwnam_r"); + } + exit(1); + } + + g = grp.gr_gid; + free(buf); + + return g; +} diff --git a/numlib/numlib.h b/numlib/numlib.h index 1aa3386..ecc75ad 100644 --- a/numlib/numlib.h +++ b/numlib/numlib.h @@ -95,6 +95,9 @@ void libmail_changeusername(const char *, const gid_t *); ** no aux group IDs for the user, any AUX ids are cleared. */ +uid_t libmail_getuid(const char *, gid_t *); +gid_t libmail_getgid(const char *); + #ifdef __cplusplus } #endif |
