Hi all,
I'm having difficulties with Solaris privileges and seteuid().
I have a forking daemon process running as root. The process is afpd
from the Netatalk (OS AFP fileserver). The main afpd process accepts
network connections, authenticates users (through PAM) and, forks and
runs seteuid(USER).
Occasionally the process calls seteuid(0) to execute priviliged
operations and then goes seteuid(USER) back again.
This all works find with local Solaris users. Now I've added Active
Directory to the mix (smbadm join, nss_ad, pam_krb5). Works fine
execpt for one issue which is a result of the following idmap
restriction
man idmap
...
To prevent aliasing problems, all file systems, archive and
backup formats, and protocols must store SIDs or map all
UIDs and GIDs in the 2^31 to 2^32 - 2 range to the nobody
user and group.
...
This means any file created by an afpd process (Solaris CIFS/NFS don't
have this issue) running with the effective uid of an AD user is
created with and owner/group of nobody:
root@oi:~# ps -elf | grep aduser
0 S aduser@a 12440 12193 0 40 20 ? 4518 ? 15:03:12 ? 0:00
/usr/local/netatalk/sbin/afpd -d -F
root@oi:~# pcred 12440
12440: euid=2147500125 ruid=0 suid=0 egid=2147491842 rgid=0 sgid=0
root@oi:~# getent passwd [email protected]
[email protected]:x:2147500125:2147491842:AD User::/bin/sh
...create file via AFP (touch /Volumes/test/afpfile1 on a Mac)...
root@oi:~# ls -l /Volumes/test/afpfile1
-rw-rw-rw- 1 nobody nobody 0 Aug 15 15:04 /Volumes/test/afpfile1
The file "afpfile1" was created by the afpd process [12440] with a
call to open(...O_CREAT...).
I know from writing a simple test program (see below) that a possible
workaround to enforce owner/group for file is just calling chown on
them. This works with chown(1)
root@oi:~# chown [email protected] /Volumes/test/afpfile1
root@oi:~# ls -l /Volumes/test/afpfile1
-rw-rw-rw- 1 [email protected] nobody 0 Aug 15 15:04
/Volumes/test/afpfile1
...and it works in the test program, unfortunately it doesn't work for
afpd, all I get is EPERM (missing privilege file_chown_self). As I'm
wrapping the fchwon call between seteuid(0) and seteuid(USER) and I've
also verified that PAS (privilege awareness state) for the process is
0 by call getpflags(PRIV_AWARE) before the call to chmod:
Code:
LOG(log_note, logtype_afpd, "afp_createfile: PAS: %s",
getpflags(PRIV_AWARE) ? "PRIV_AWARE" : "not PRIV_AWARE");
Log:
Aug 15 15:06:42.083590 afpd[12440] {file.c:732} (N:AFPDaemon):
afp_createfile: PAS: not PRIV_AWARE
truss shows:
root@oi:~# truss -v all -t fchown,seteuid -p 12440
seteuid(0) = 0
fchown(10, -2147467171, -2147475454) Err#1 EPERM [file_chown_self]
seteuid(2147500125) = 0
The negative uid and gid for fchown are ok, truss interprets the
ephemeral ids (defined to be >0x8000000) as negative numbers.
root@oi:~# ppriv 12440
12440: /usr/local/netatalk/sbin/afpd -d -F /usr/local/netatalk/etc/afp.conf
flags = <none>
E: basic
I: basic
P: all
L: all
No matter what I try (increasing privileges for the process with eg
ppriv -s EIPL=all PID), it always fails with EPERM which strikes me as
it is demonstratably doing the fchown() with an effective uid of 0.
I highly appreciate any insight or pointers. There's a budget for paid
consulting, you can also contact me by PM if your interested and you
think you can help.
Thank you!
-f
---8<---
/*
* gcc -o seteuid seteuid.c
*/
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>
#define ERROR(msg) do { perror(msg); exit(1); } while (0)
int wait_for_key(void)
{
printf(" [Press RETURN to continue...]");
getchar();
}
int main (int argc, char **argv)
{
struct stat st;
const char *name, *file;
struct passwd *pwd;
int fd;
if (argc < 3) {
printf("usage: %s USERNAME FILENAME\n", argv[0]);
exit(1);
}
name = argv[1];
file = argv[2];
if (getuid() != 0) {
printf("Must be run with uid 0 (root)\n");
exit(1);
}
if ((pwd = getpwnam(name)) == NULL)
ERROR("getpwnam");
printf("name: %s, uid: %u\n", name, pwd->pw_uid);
printf("switching effective uid to %u", pwd->pw_uid);
wait_for_key();
if (seteuid(pwd->pw_uid) != 0)
ERROR("seteuid");
printf("creating file ...");
wait_for_key();
if ((fd = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
ERROR("creat");
if (fstat(fd, &st) != 0)
ERROR("fstat");
printf("file owner uid: %u\n", st.st_uid);
printf("switch effective uid back to 0 (root) ...");
wait_for_key();
if (seteuid(0) != 0)
ERROR("seteuid");
printf("Try to change owner of testfile to %u", pwd->pw_uid);
wait_for_key();
if (fchown(fd, pwd->pw_uid) != 0)
ERROR("fchown");
close(fd);
return 0;
}
---8<---
_______________________________________________
OpenIndiana-discuss mailing list
[email protected]
http://openindiana.org/mailman/listinfo/openindiana-discuss