#ifndef __CONNECT_H__ #define __CONNECT_H__ #include #include #include #include #include "config.h" #include #include #include #include #include #ifndef SUN_LEN #define SUN_LEN(ptr) ((socklen_t) (((struct sockaddr_un *) 0)->sun_path) \ + strlen ((ptr)->sun_path)) #endif #include "common.h" #include "config.h" #ifdef __cplusplus typedef bool kgtk_bool; #define KGTK_TRUE true #define KGTK_FALSE false #else typedef gboolean kgtk_bool; #define KGTK_TRUE TRUE #define KGTK_FALSE FALSE #endif static int kdialogdSocket=-1; /* From kdelibs/kdesu */ #ifdef KDIALOGD_APP static int createSocketConnectionReal() #else static int createSocketConnection() #endif { #ifdef KGTK_DEBUG printf("KGTK::createSocketConnection A\n"); #endif int sockfd=-1; const char *sock=getSockName(); struct sockaddr_un addr; if (access(sock, R_OK|W_OK)) { #ifdef KGTK_DEBUG printf("Could not access socket, %s\n", sock); #endif return -1; } sockfd = socket(PF_UNIX, SOCK_STREAM, 0); if (sockfd < 0) { #ifdef KGTK_DEBUG printf("Could not create socket, %d\n", errno); #endif return -1; } addr.sun_family = AF_UNIX; strcpy(addr.sun_path, sock); if (connect(sockfd, (struct sockaddr *) &addr, SUN_LEN(&addr)) < 0) { #ifdef KGTK_DEBUG printf("Could not connect socket, %d\n", errno); #endif close(sockfd); return -1; } #if !defined(SO_PEERCRED) || !defined(HAVE_STRUCT_UCRED) # if defined(HAVE_GETPEEREID) { uid_t euid; gid_t egid; /* Security: if socket exists, we must own it */ if (getpeereid(sockfd, &euid, &egid) == 0) { if (euid != getuid()) { #ifdef KGTK_DEBUG printf("socket not owned by me! socket uid %d\n", euid); #endif close(sockfd); return -1; } } } # else # ifdef __GNUC__ # warning "Using sloppy security checks" # endif /* We check the owner of the socket after we have connected. If the socket was somehow not ours an attacker will be able to delete it after we connect but shouldn't be able to create a socket that is owned by us. */ { struct stat s; if (lstat(sock, &s)!=0) { #ifdef KGTK_DEBUG printf("stat failed %s\n", sock); #endif close(sockfd); return -1; } if (s.st_uid != getuid()) { #ifdef KGTK_DEBUG printf("socket not owned by me! socket uid %d\n", s.st_uid); #endif close(sockfd); return -1; } if (!S_ISSOCK(s.st_mode)) { #ifdef KGTK_DEBUG printf("socket is not a socket %s\n", sock); #endif close(sockfd); return -1; } } # endif #else { struct ucred cred; socklen_t siz = sizeof(cred); /* Security: if socket exists, we must own it */ if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) == 0) { if (cred.uid != getuid()) { #ifdef KGTK_DEBUG printf("socket not owned by me! socket uid %d\n", cred.uid); #endif close(sockfd); return -1; } } } #endif #ifdef KGTK_DEBUG printf("KGTK::createSocketConnection sockfd:%d\n", sockfd); #endif return sockfd; } #ifdef KDIALOGD_APP static int createSocketConnection() { int rv=-1, tries=0; do { if(-1==(rv=createSocketConnectionReal())) usleep(10000); } while(-1==rv && ++tries<50); if(-1==rv) fprintf(stderr, "ERROR: Could not talk to KDialogD!!!\n"); return rv; } #endif /* Note: Calling 'fork' seems to mess things up with eclipse! */ #define KGTK_USE_SYSTEM_CALL static kgtk_bool connectToKDialogD(const char *appName) { if(-1!=kdialogdSocket) return KGTK_TRUE; else { unsigned int slen=strlen(appName); kgtk_bool rv=KGTK_TRUE; if(slen) slen++; #ifdef KDIALOGD_APP grabLock(5); #ifdef KGTK_USE_SYSTEM_CALL system("kdialogd-wrapper &"); #else switch(fork()) { case -1: rv=KGTK_FALSE; printf("ERROR: Could not start fork :-(\n"); break; case 0: execl(KDIALOGD_LOCATION"/kdialogd-wrapper", "kdialogd-wrapper", (char *)NULL); break; default: { int status=0; wait(&status); } } #endif releaseLock(); #endif if(!rv) return rv; rv= #ifdef KDIALOGD_APP grabLock(3)>0 && #else 0==system("dcop kded kded loadModule kdialogd") && #endif -1!=(kdialogdSocket=createSocketConnection()) && writeBlock(kdialogdSocket, (char *)&slen, 4) && (0==slen || writeBlock(kdialogdSocket, appName, slen)); #ifdef KDIALOGD_APP releaseLock(); #endif return rv; } } static void closeConnection() { close(kdialogdSocket); kdialogdSocket=-1; } #endif