/* getpeercred.c - function for determining information about the other end of a unix socket This file is part of the nss-pam-ldapd library. Copyright (C) 2008 Arthur de Jong This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #ifdef HAVE_SYS_UCRED_H #include #endif /* HAVE SYS_UCRED_H */ #include #ifdef HAVE_UCRED_H #include #endif /* HAVE_UCRED_H */ #include "getpeercred.h" /* Note: most of this code is untested, except for the first implementation (it may even fail to compile) */ int getpeercred(int sock,uid_t *uid,gid_t *gid,pid_t *pid) { #if defined(SO_PEERCRED) socklen_t l; struct ucred cred; /* initialize client information (in case getsockopt() breaks) */ cred.pid=(pid_t)0; cred.uid=(uid_t)-1; cred.gid=(gid_t)-1; /* look up process information from peer */ l=(socklen_t)sizeof(struct ucred); if (getsockopt(sock,SOL_SOCKET,SO_PEERCRED,&cred,&l) < 0) return -1; /* errno already set */ /* return the data */ if (uid!=NULL) *uid=cred.uid; if (gid!=NULL) *gid=cred.gid; if (pid!=NULL) *pid=cred.pid; return 0; #elif defined(LOCAL_PEERCRED) socklen_t l; struct xucred cred; /* look up process information from peer */ l=(socklen_t)sizeof(struct xucred); if (getsockopt(sock,0,LOCAL_PEERCRED,&cred,&l) < 0) return -1; /* errno already set */ if (cred.cr_version!=XUCRED_VERSION) { errno=EINVAL; return -1; } /* return the data */ if (uid!=NULL) *uid=cred.cr_uid; if (gid!=NULL) *gid=cred.cr_gid; if (pid!=NULL) *pid=(pid_t)-1; return 0; #elif defined(HAVE_GETPEERUCRED) ucred_t *cred=NULL; if (getpeerucred(sock,&cred)) return -1; /* save the data */ if (uid!=NULL) *uid=ucred_geteuid(cred); if (gid!=NULL) *gid=ucred_getegid(cred); if (pid!=NULL) *pid=ucred_getpid(cred); /* free cred and return */ ucred_free(cred); return 0; #elif defined(HAVE_GETPEEREID) uid_t tuid; gid_t tgid; if (uid==NULL) uid=&tuid; if (gid==NULL) gid=&tguid; if (getpeereid(sock,uid,gid)) return -1; /* return the data */ if (uid!=NULL) *uid=cred.uid; if (gid!=NULL) *gid=cred.gid; if (pid!=NULL) *pid=-1; /* we return a -1 pid because we have no usable pid */ return 0; #else /* nothing found that is supported */ errno=ENOSYS; return -1; #endif }