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; }