Secure promiscuous modetags/v1.9.12
| @@ -0,0 +1,95 @@ | |||||
| /* | |||||
| Copyright (C) 2014-2017 Cédric Schieli | |||||
| This program is free software; you can redistribute it and/or | |||||
| modify it under the terms of the GNU General Public License | |||||
| as published by the Free Software Foundation; either version 2 | |||||
| of the License, or (at your option) any later version. | |||||
| This program 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 General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||||
| */ | |||||
| #ifndef WIN32 | |||||
| #include <stdlib.h> | |||||
| #include <unistd.h> | |||||
| #include <errno.h> | |||||
| #include <sys/types.h> | |||||
| #include <sys/stat.h> | |||||
| #include <fcntl.h> | |||||
| #include <grp.h> | |||||
| #ifdef __APPLE__ | |||||
| #include <AvailabilityMacros.h> | |||||
| #endif | |||||
| #include "JackError.h" | |||||
| #endif | |||||
| int | |||||
| jack_group2gid(const char* group) | |||||
| { | |||||
| #ifdef WIN32 | |||||
| return -1; | |||||
| #else | |||||
| size_t buflen; | |||||
| char *buf; | |||||
| int ret; | |||||
| struct group grp; | |||||
| struct group *result; | |||||
| if (!group || !*group) | |||||
| return -1; | |||||
| ret = strtol(group, &buf, 10); | |||||
| if (!*buf) | |||||
| return ret; | |||||
| /* MacOSX only defines _SC_GETGR_R_SIZE_MAX starting from 10.4 */ | |||||
| #if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 | |||||
| buflen = 4096; | |||||
| #else | |||||
| buflen = sysconf(_SC_GETGR_R_SIZE_MAX); | |||||
| if (buflen == -1) | |||||
| buflen = 4096; | |||||
| #endif | |||||
| buf = (char*)malloc(buflen); | |||||
| while (buf && ((ret = getgrnam_r(group, &grp, buf, buflen, &result)) == ERANGE)) { | |||||
| buflen *= 2; | |||||
| buf = (char*)realloc(buf, buflen); | |||||
| } | |||||
| if (!buf) | |||||
| return -1; | |||||
| free(buf); | |||||
| if (ret || !result) | |||||
| return -1; | |||||
| return grp.gr_gid; | |||||
| #endif | |||||
| } | |||||
| #ifndef WIN32 | |||||
| int | |||||
| jack_promiscuous_perms(int fd, const char* path, gid_t gid) | |||||
| { | |||||
| mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; | |||||
| if (gid >= 0) { | |||||
| if (((fd < 0) ? chown(path, -1, gid) : fchown(fd, -1, gid)) < 0) { | |||||
| jack_log("Cannot chgrp %s: %s. Falling back to permissive perms.", path, strerror(errno)); | |||||
| } else { | |||||
| mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; | |||||
| } | |||||
| } | |||||
| if (((fd < 0) ? chmod(path, mode) : fchmod(fd, mode)) < 0) { | |||||
| jack_log("Cannot chmod %s: %s. Falling back to default (umask) perms.", path, strerror(errno)); | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| #endif | |||||
| @@ -0,0 +1,39 @@ | |||||
| /* | |||||
| Copyright (C) 2014-2017 Cédric Schieli | |||||
| This program is free software; you can redistribute it and/or | |||||
| modify it under the terms of the GNU General Public License | |||||
| as published by the Free Software Foundation; either version 2 | |||||
| of the License, or (at your option) any later version. | |||||
| This program 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 General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||||
| */ | |||||
| #ifndef __jack_gid_h__ | |||||
| #define __jack_gid_h__ | |||||
| #ifdef __cplusplus | |||||
| extern "C" | |||||
| { | |||||
| #endif | |||||
| int jack_group2gid (const char *group); /*!< Lookup gid for a UNIX group in a thread-safe way */ | |||||
| #ifndef WIN32 | |||||
| int jack_promiscuous_perms (int fd, const char *path, gid_t gid); /*!< Set promiscuous permissions on object referenced by fd and/or path */ | |||||
| #endif | |||||
| #ifdef __cplusplus | |||||
| } | |||||
| #endif | |||||
| #endif /* __jack_gid_h__ */ | |||||
| @@ -52,6 +52,7 @@ | |||||
| #include <sys/shm.h> | #include <sys/shm.h> | ||||
| #include <sys/sem.h> | #include <sys/sem.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include "promiscuous.h" | |||||
| #endif | #endif | ||||
| @@ -837,6 +838,7 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) | |||||
| int shm_fd; | int shm_fd; | ||||
| int rc = -1; | int rc = -1; | ||||
| char name[SHM_NAME_MAX+1]; | char name[SHM_NAME_MAX+1]; | ||||
| const char* promiscuous; | |||||
| if (jack_shm_lock_registry () < 0) { | if (jack_shm_lock_registry () < 0) { | ||||
| jack_error ("jack_shm_lock_registry fails..."); | jack_error ("jack_shm_lock_registry fails..."); | ||||
| @@ -877,6 +879,10 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) | |||||
| goto unlock; | goto unlock; | ||||
| } | } | ||||
| promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); | |||||
| if ((promiscuous != NULL) && (jack_promiscuous_perms(shm_fd, name, jack_group2gid(promiscuous)) < 0)) | |||||
| goto unlock; | |||||
| close (shm_fd); | close (shm_fd); | ||||
| registry->size = size; | registry->size = size; | ||||
| strncpy (registry->id, name, sizeof (registry->id)); | strncpy (registry->id, name, sizeof (registry->id)); | ||||
| @@ -80,6 +80,7 @@ def build(bld): | |||||
| common_libsources += [ | common_libsources += [ | ||||
| 'JackDebugClient.cpp', | 'JackDebugClient.cpp', | ||||
| 'timestamps.c', | 'timestamps.c', | ||||
| 'promiscuous.c', | |||||
| '../posix/JackPosixThread.cpp', | '../posix/JackPosixThread.cpp', | ||||
| '../posix/JackPosixProcessSync.cpp', | '../posix/JackPosixProcessSync.cpp', | ||||
| '../posix/JackPosixMutex.cpp', | '../posix/JackPosixMutex.cpp', | ||||
| @@ -95,6 +96,7 @@ def build(bld): | |||||
| common_libsources += [ | common_libsources += [ | ||||
| 'JackDebugClient.cpp', | 'JackDebugClient.cpp', | ||||
| 'timestamps.c', | 'timestamps.c', | ||||
| 'promiscuous.c', | |||||
| '../posix/JackPosixThread.cpp', | '../posix/JackPosixThread.cpp', | ||||
| '../posix/JackFifo.cpp', | '../posix/JackFifo.cpp', | ||||
| '../posix/JackPosixProcessSync.cpp', | '../posix/JackPosixProcessSync.cpp', | ||||
| @@ -109,6 +111,7 @@ def build(bld): | |||||
| common_libsources += [ | common_libsources += [ | ||||
| 'JackDebugClient.cpp', | 'JackDebugClient.cpp', | ||||
| 'timestamps.c', | 'timestamps.c', | ||||
| 'promiscuous.c', | |||||
| '../posix/JackPosixProcessSync.cpp', | '../posix/JackPosixProcessSync.cpp', | ||||
| '../posix/JackPosixThread.cpp', | '../posix/JackPosixThread.cpp', | ||||
| '../posix/JackPosixMutex.cpp', | '../posix/JackPosixMutex.cpp', | ||||
| @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include "JackTools.h" | #include "JackTools.h" | ||||
| #include "JackConstants.h" | #include "JackConstants.h" | ||||
| #include "JackError.h" | #include "JackError.h" | ||||
| #include "promiscuous.h" | |||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||
| @@ -31,11 +32,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| JackLinuxFutex::JackLinuxFutex() : JackSynchro(), fSharedMem(-1), fFutex(NULL), fPrivate(false) | |||||
| { | |||||
| const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); | |||||
| fPromiscuous = (promiscuous != NULL); | |||||
| fPromiscuousGid = jack_group2gid(promiscuous); | |||||
| } | |||||
| void JackLinuxFutex::BuildName(const char* client_name, const char* server_name, char* res, int size) | void JackLinuxFutex::BuildName(const char* client_name, const char* server_name, char* res, int size) | ||||
| { | { | ||||
| char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | ||||
| JackTools::RewriteName(client_name, ext_client_name); | JackTools::RewriteName(client_name, ext_client_name); | ||||
| if (getenv("JACK_PROMISCUOUS_SERVER")) { | |||||
| if (fPromiscuous) { | |||||
| snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); | snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); | ||||
| } else { | } else { | ||||
| snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | ||||
| @@ -132,6 +140,13 @@ bool JackLinuxFutex::Allocate(const char* name, const char* server_name, int val | |||||
| ftruncate(fSharedMem, sizeof(FutexData)); | ftruncate(fSharedMem, sizeof(FutexData)); | ||||
| if (fPromiscuous && (jack_promiscuous_perms(fSharedMem, fName, fPromiscuousGid) < 0)) { | |||||
| close(fSharedMem); | |||||
| fSharedMem = -1; | |||||
| shm_unlink(fName); | |||||
| return false; | |||||
| } | |||||
| if ((fFutex = (FutexData*)mmap(NULL, sizeof(FutexData), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fSharedMem, 0)) == NULL) { | if ((fFutex = (FutexData*)mmap(NULL, sizeof(FutexData), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fSharedMem, 0)) == NULL) { | ||||
| jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); | jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); | ||||
| close(fSharedMem); | close(fSharedMem); | ||||
| @@ -53,6 +53,8 @@ class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro | |||||
| int fSharedMem; | int fSharedMem; | ||||
| FutexData* fFutex; | FutexData* fFutex; | ||||
| bool fPrivate; | bool fPrivate; | ||||
| bool fPromiscuous; | |||||
| int fPromiscuousGid; | |||||
| protected: | protected: | ||||
| @@ -60,8 +62,7 @@ class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro | |||||
| public: | public: | ||||
| JackLinuxFutex():JackSynchro(), fSharedMem(-1), fFutex(NULL), fPrivate(false) | |||||
| {} | |||||
| JackLinuxFutex(); | |||||
| bool Signal(); | bool Signal(); | ||||
| bool SignalAll(); | bool SignalAll(); | ||||
| @@ -24,10 +24,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <sys/time.h> | #include <sys/time.h> | ||||
| #ifdef __linux__ | |||||
| #include "promiscuous.h" | |||||
| #endif | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| JackPosixSemaphore::JackPosixSemaphore() : JackSynchro(), fSemaphore(NULL) | |||||
| { | |||||
| const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); | |||||
| fPromiscuous = (promiscuous != NULL); | |||||
| #ifdef __linux__ | |||||
| fPromiscuousGid = jack_group2gid(promiscuous); | |||||
| #endif | |||||
| } | |||||
| void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size) | void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size) | ||||
| { | { | ||||
| char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | ||||
| @@ -35,7 +47,7 @@ void JackPosixSemaphore::BuildName(const char* client_name, const char* server_n | |||||
| #if __APPLE__ // POSIX semaphore names are limited to 32 characters... | #if __APPLE__ // POSIX semaphore names are limited to 32 characters... | ||||
| snprintf(res, 32, "js_%s", ext_client_name); | snprintf(res, 32, "js_%s", ext_client_name); | ||||
| #else | #else | ||||
| if (getenv("JACK_PROMISCUOUS_SERVER")) { | |||||
| if (fPromiscuous) { | |||||
| snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); | snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); | ||||
| } else { | } else { | ||||
| snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | ||||
| @@ -147,6 +159,14 @@ bool JackPosixSemaphore::Allocate(const char* name, const char* server_name, int | |||||
| jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); | jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); | ||||
| return false; | return false; | ||||
| } else { | } else { | ||||
| #ifdef __linux__ | |||||
| if (fPromiscuous) { | |||||
| char sempath[SYNC_MAX_NAME_SIZE+13]; | |||||
| snprintf(sempath, sizeof(sempath), "/dev/shm/sem.%s", fName); | |||||
| if (jack_promiscuous_perms(-1, sempath, fPromiscuousGid) < 0) | |||||
| return false; | |||||
| } | |||||
| #endif | |||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| @@ -39,6 +39,10 @@ class SERVER_EXPORT JackPosixSemaphore : public detail::JackSynchro | |||||
| private: | private: | ||||
| sem_t* fSemaphore; | sem_t* fSemaphore; | ||||
| bool fPromiscuous; | |||||
| #ifdef __linux__ | |||||
| int fPromiscuousGid; | |||||
| #endif | |||||
| protected: | protected: | ||||
| @@ -46,8 +50,7 @@ class SERVER_EXPORT JackPosixSemaphore : public detail::JackSynchro | |||||
| public: | public: | ||||
| JackPosixSemaphore():JackSynchro(), fSemaphore(NULL) | |||||
| {} | |||||
| JackPosixSemaphore(); | |||||
| bool Signal(); | bool Signal(); | ||||
| bool SignalAll(); | bool SignalAll(); | ||||
| @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| #include "JackConstants.h" | #include "JackConstants.h" | ||||
| #include "JackTools.h" | #include "JackTools.h" | ||||
| #include "JackError.h" | #include "JackError.h" | ||||
| #include "promiscuous.h" | |||||
| #include <string.h> | #include <string.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <pthread.h> | #include <pthread.h> | ||||
| @@ -29,18 +30,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| static void BuildName(const char* client_name, char* res, const char* dir, int which, int size) | |||||
| static void BuildName(const char* client_name, char* res, const char* dir, int which, int size, bool promiscuous) | |||||
| { | { | ||||
| char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | ||||
| JackTools::RewriteName(client_name, ext_client_name); | JackTools::RewriteName(client_name, ext_client_name); | ||||
| if (getenv("JACK_PROMISCUOUS_SERVER")) { | |||||
| if (promiscuous) { | |||||
| snprintf(res, size, "%s/jack_%s_%d", dir, ext_client_name, which); | snprintf(res, size, "%s/jack_%s_%d", dir, ext_client_name, which); | ||||
| } else { | } else { | ||||
| snprintf(res, size, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which); | snprintf(res, size, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which); | ||||
| } | } | ||||
| } | } | ||||
| JackClientSocket::JackClientSocket(int socket): JackClientRequestInterface(), fSocket(socket),fTimeOut(0) | |||||
| JackClientSocket::JackClientSocket(): JackClientRequestInterface(), fSocket(-1), fTimeOut(0) | |||||
| { | |||||
| const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); | |||||
| fPromiscuous = (promiscuous != NULL); | |||||
| fPromiscuousGid = jack_group2gid(promiscuous); | |||||
| } | |||||
| JackClientSocket::JackClientSocket(int socket): JackClientRequestInterface(), fSocket(socket),fTimeOut(0), fPromiscuous(false), fPromiscuousGid(-1) | |||||
| {} | {} | ||||
| #if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
| @@ -123,7 +131,7 @@ int JackClientSocket::Connect(const char* dir, const char* name, int which) // A | |||||
| } | } | ||||
| addr.sun_family = AF_UNIX; | addr.sun_family = AF_UNIX; | ||||
| BuildName(name, addr.sun_path, dir, which, sizeof(addr.sun_path)); | |||||
| BuildName(name, addr.sun_path, dir, which, sizeof(addr.sun_path), fPromiscuous); | |||||
| jack_log("JackClientSocket::Connect : addr.sun_path %s", addr.sun_path); | jack_log("JackClientSocket::Connect : addr.sun_path %s", addr.sun_path); | ||||
| if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | ||||
| @@ -247,6 +255,13 @@ int JackClientSocket::Write(void* data, int len) | |||||
| } | } | ||||
| } | } | ||||
| JackServerSocket::JackServerSocket(): fSocket( -1) | |||||
| { | |||||
| const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); | |||||
| fPromiscuous = (promiscuous != NULL); | |||||
| fPromiscuousGid = jack_group2gid(promiscuous); | |||||
| } | |||||
| int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which" | int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which" | ||||
| { | { | ||||
| struct sockaddr_un addr; | struct sockaddr_un addr; | ||||
| @@ -258,7 +273,7 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re | |||||
| addr.sun_family = AF_UNIX; | addr.sun_family = AF_UNIX; | ||||
| // Socket name has to be kept in fName to be "unlinked". | // Socket name has to be kept in fName to be "unlinked". | ||||
| BuildName(name, fName, dir, which, sizeof(addr.sun_path)); | |||||
| BuildName(name, fName, dir, which, sizeof(addr.sun_path), fPromiscuous); | |||||
| strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); | strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); | ||||
| jack_log("JackServerSocket::Bind : addr.sun_path %s", addr.sun_path); | jack_log("JackServerSocket::Bind : addr.sun_path %s", addr.sun_path); | ||||
| @@ -274,6 +289,9 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re | |||||
| goto error; | goto error; | ||||
| } | } | ||||
| if (fPromiscuous && (jack_promiscuous_perms(-1, fName, fPromiscuousGid) < 0)) | |||||
| goto error; | |||||
| return 0; | return 0; | ||||
| error: | error: | ||||
| @@ -45,11 +45,12 @@ class JackClientSocket : public detail::JackClientRequestInterface | |||||
| int fSocket; | int fSocket; | ||||
| int fTimeOut; | int fTimeOut; | ||||
| bool fPromiscuous; | |||||
| int fPromiscuousGid; | |||||
| public: | public: | ||||
| JackClientSocket():JackClientRequestInterface(), fSocket(-1), fTimeOut(0) | |||||
| {} | |||||
| JackClientSocket(); | |||||
| JackClientSocket(int socket); | JackClientSocket(int socket); | ||||
| int Connect(const char* dir, const char* name, int which); | int Connect(const char* dir, const char* name, int which); | ||||
| @@ -80,11 +81,12 @@ class JackServerSocket | |||||
| int fSocket; | int fSocket; | ||||
| char fName[SOCKET_MAX_NAME_SIZE]; | char fName[SOCKET_MAX_NAME_SIZE]; | ||||
| bool fPromiscuous; | |||||
| int fPromiscuousGid; | |||||
| public: | public: | ||||
| JackServerSocket(): fSocket( -1) | |||||
| {} | |||||
| JackServerSocket(); | |||||
| ~JackServerSocket() | ~JackServerSocket() | ||||
| {} | {} | ||||