On Thu, Jan 27, 2022 at 02:46:04PM -0500, Viktor Dukhovni wrote:
> Perhaps your Kerberos (GSSAPI via SASL?) library is ignoring environment
> variables in processes that change uids (smtpd starts as root and then
> drops privs). Of course that makes sense for a setuid process, but not
> so much for a proces that starts as root... The Fedora 31
> secure_getenv(3) manpage says:
See, for example, the MIT implementation:
https://github.com/krb5/krb5/blob/master/src/lib/krb5/os/ktdefname.c#L44-L47
static krb5_error_code
kt_default_name(krb5_context context, char **name_out)
...
} else if (context->profile_secure == FALSE &&
(str = secure_getenv("KRB5_KTNAME")) != NULL) {
*name_out = strdup(str);
return (*name_out == NULL) ? ENOMEM : 0;
...
> You'll need to try a test program that starts as root, then changes
> uid to (e.g.) "postfix", and see whether "secure_getenv()" reports
> the expected environment variables.
>
> The most likely reasons for changes are in Cyrus SASL, not Postfix,
> which does not directly do anything with Kerberos.
On Fedora 31 (now dated), secure_getenv(3) does not suppress environment
variables in processes that drop privs. See attached test program.
# KRB5_KTNAME=FILE:/etc/postfix/smtp.keytab /tmp/suid -u 89 -v KRB5_KTNAME
uid = 89, euid=89, suid=89
getenv('KRB5_KTNAME') = FILE:/etc/postfix/smtp.keytab
secure_getenv('KRB5_KTNAME') = FILE:/etc/postfix/smtp.keytab
Note that the keytab file in question does need to be readable by
the "postfix" user, not just "root". The smtpd(8) process drops
privs.
--
Viktor.
#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>
int main(int argc, char *argv[])
{
const char *var = "HOME";
uid_t uid = 0;
uid_t euid = 0;
uid_t suid = 0;
int c;
while ((c = getopt(argc, argv, "u:v:")) != EOF) {
switch (c) {
case 'u':
uid = (uid_t) atoi(optarg);
break;
case 'v':
var = optarg;
break;
default:
errx(1, "Usage: %s [-u uid] [-v var]", argv[0]);
break;
}
}
if (uid != 0) {
if (setuid(uid) != 0)
err(1, "%s: setuid", argv[0]);
}
if (getresuid(&uid, &euid, &suid) != 0)
err(1, "%s: getresuid", argv[0]);
printf("uid = %d, euid=%d, suid=%d\n",
(int) uid, (int) euid, (int) suid);
printf("getenv('%s') = %s\n", var, getenv(var));
printf("secure_getenv('%s') = %s\n", var, secure_getenv(var));
return 0;
}