From 419a62c9b9bfed6f9df52be8e63639b4d0d8ae12 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 7 Apr 2017 13:33:29 +0200 Subject: [PATCH 1/1] add compat layer to handle both fifos and sockets So far screen could only support either sockets or fifos but not both. This proved to be a blocker for any upgrade. This adds a compatibility layer to screen v4 to support both sockets and fifos at the same time. The strategy here is to only support fifos for legacy sessions that already exist. All new sessions will use sockets by default. Signed-off-by: Christian Brauner --- acconfig.h | 5 - attacher.c | 30 +- configure.ac | 26 -- extern.h | 9 +- osdef.h.in | 3 - osdef.sh | 2 - screen.c | 32 +- socket.c | 930 ++++++++++++++++++++++++++++++----------------------------- 8 files changed, 504 insertions(+), 533 deletions(-) diff --git a/acconfig.h b/acconfig.h index 2e46985..4e5cda0 100644 --- a/acconfig.h +++ b/acconfig.h @@ -504,11 +504,6 @@ #undef SELECT_BROKEN /* - * Define this if your system supports named pipes. - */ -#undef NAMEDPIPE - -/* * Define this if your system exits select() immediatly if a pipe is * opened read-only and no writer has opened it. */ diff --git a/attacher.c b/attacher.c index ed0d6ea..196993f 100644 --- a/attacher.c +++ b/attacher.c @@ -120,11 +120,11 @@ int s; struct msg *m; { int r, l = sizeof(*m); + bool is_socket; -#ifndef NAMEDPIPE - if (m->type == MSG_ATTACH) + is_socket = IsSocket(SockPath); + if (is_socket && m->type == MSG_ATTACH) return SendAttachMsg(s, m, attach_fd); -#endif while(l > 0) { @@ -147,6 +147,7 @@ int how; struct msg m; struct stat st; char *s; + bool is_socket; debug2("Attach: how=%d, tty=%s\n", how, attach_tty); #ifdef MULTIUSER @@ -234,9 +235,10 @@ int how; strncpy(m.m_tty, attach_tty_is_in_new_ns ? attach_tty_name_in_ns : attach_tty, sizeof(m.m_tty) - 1); m.m_tty[sizeof(m.m_tty) - 1] = 0; + is_socket = IsSocket(SockPath); if (how == MSG_WINCH) { - if ((lasts = MakeClientSocket(0)) >= 0) + if ((lasts = MakeClientSocket(0, is_socket)) >= 0) { WriteMessage(lasts, &m); close(lasts); @@ -246,7 +248,7 @@ int how; if (how == MSG_CONT) { - if ((lasts = MakeClientSocket(0)) < 0) + if ((lasts = MakeClientSocket(0, is_socket)) < 0) { Panic(0, "Sorry, cannot contact session \"%s\" again.\r\n", SockName); @@ -254,7 +256,7 @@ int how; } else { - n = FindSocket(&lasts, (int *)0, (int *)0, SockMatch); + n = FindSocket(&lasts, (int *)0, (int *)0, SockMatch, &is_socket); switch (n) { case 0: @@ -363,7 +365,7 @@ int how; if (how != MSG_ATTACH) return 0; /* we detached it. jw. */ sleep(1); /* we dont want to overrun our poor backend. jw. */ - if ((lasts = MakeClientSocket(0)) == -1) + if ((lasts = MakeClientSocket(0, is_socket)) == -1) Panic(0, "Cannot contact screen again. Sigh."); m.type = how; } @@ -479,6 +481,7 @@ AttacherFinit SIGDEFARG struct stat statb; struct msg m; int s; + bool is_socket; debug("AttacherFinit();\n"); signal(SIGHUP, SIG_IGN); @@ -493,7 +496,8 @@ AttacherFinit SIGDEFARG m.m.detach.dpid = getpid(); m.type = MSG_HANGUP; m.protocol_revision = MSG_REVISION; - if ((s = MakeClientSocket(0)) >= 0) + is_socket = IsSocket(SockPath); + if ((s = MakeClientSocket(0, is_socket)) >= 0) { WriteMessage(s, &m); close(s); @@ -1002,10 +1006,11 @@ int query; struct msg m; char *p; int len, n; + bool is_socket; if (sty == 0) { - i = FindSocket(&s, (int *)0, (int *)0, match); + i = FindSocket(&s, (int *)0, (int *)0, match, &is_socket); if (i == 0) Panic(0, "No screen session found."); if (i != 1) @@ -1020,7 +1025,8 @@ int query; if (strlen(sty) > 2 * MAXSTR - 1) sty[2 * MAXSTR - 1] = 0; sprintf(SockPath + strlen(SockPath), "/%s", sty); - if ((s = MakeClientSocket(1)) == -1) + is_socket = IsSocket(SockPath); + if ((s = MakeClientSocket(1, is_socket)) == -1) exit(1); } bzero((char *)&m, sizeof(m)); @@ -1060,7 +1066,7 @@ int query; { query[6] = c; strcpy(sp, query); /* XXX: strncpy? */ - if ((r = MakeServerSocket()) >= 0) + if ((r = MakeServerSocket(is_socket)) >= 0) break; } if (r < 0) @@ -1069,7 +1075,7 @@ int query; { query[6] = c; strcpy(sp, query); - if ((r = MakeServerSocket()) >= 0) + if ((r = MakeServerSocket(is_socket)) >= 0) break; } } diff --git a/configure.ac b/configure.ac index ccebe56..f9d758a 100644 --- a/configure.ac +++ b/configure.ac @@ -530,31 +530,9 @@ fi dnl dnl **** choose sockets or fifos **** dnl -if test -n "$fifo"; then - if test -n "$sock"; then - if test -n "$nore"; then - AC_NOTE(- hmmm... better take the fifos) - AC_DEFINE(NAMEDPIPE) - elif test -n "$fifobr"; then - AC_NOTE(- as your fifos are broken lets use the sockets.) - else - AC_NOTE(- both sockets and fifos usable. let's take sockets.) - fi - else - AC_NOTE(- using named pipes, of course) - AC_DEFINE(NAMEDPIPE) - fi -elif test -n "$sock"; then - AC_NOTE(- using unix-domain sockets, of course) -else - AC_MSG_ERROR(you have neither usable sockets nor usable pipes -> no screen) -fi - -dnl dnl **** check the select implementation **** dnl -AC_CHECKING(select return value) AC_TRY_RUN([ /* For select - According to POSIX 1003.1-2001 */ #include @@ -569,14 +547,10 @@ AC_TRY_RUN([ char *nam = "/tmp/conftest$$"; -#ifdef NAMEDPIPE - #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY -#endif #ifndef S_IFIFO #define S_IFIFO 0010000 -#endif main() diff --git a/extern.h b/extern.h index 737b96a..58643a7 100644 --- a/extern.h +++ b/extern.h @@ -32,6 +32,8 @@ #define __attribute__(x) #endif +#include + /* screen.c */ extern int main __P((int, char **)); extern sigret_t SigHup __P(SIGPROTOARG); @@ -336,9 +338,9 @@ extern void SetTimeout __P((struct event *, int)); extern void sched __P((void)); /* socket.c */ -extern int FindSocket __P((int *, int *, int *, char *)); -extern int MakeClientSocket __P((int)); -extern int MakeServerSocket __P((void)); +extern int FindSocket __P((int *, int *, int *, char *, bool *)); +extern int MakeClientSocket __P((int, bool)); +extern int MakeServerSocket __P((bool)); extern int RecoverSocket __P((void)); extern int chsock __P((void)); extern void ReceiveMsg __P((void)); @@ -346,6 +348,7 @@ extern void SendCreateMsg __P((char *, struct NewWindow *)); extern int SendErrorMsg __P((char *, char *)); extern int SendAttachMsg __P((int, struct msg *, int)); extern void ReceiveRaw __P((int)); +extern bool IsSocket __P((const char *)); /* misc.c */ extern char *SaveStr __P((const char *)); diff --git a/osdef.h.in b/osdef.h.in index 3627154..0dd821e 100644 --- a/osdef.h.in +++ b/osdef.h.in @@ -147,9 +147,7 @@ extern char *malloc __P((int)); extern char *realloc __P((char *, int)); extern void free __P((char *)); -#ifdef NAMEDPIPE extern int mknod __P((char *, int, int)); -#else struct sockaddr; /* for connect __P */ extern int socket __P((int, int, int)); extern int connect __P((int, struct sockaddr *, int)); @@ -160,7 +158,6 @@ extern int accept __P((int, struct sockaddr *, socklen_t *)); #else extern int accept __P((int, struct sockaddr *, int *)); #endif -#endif #if defined(UTMPOK) && defined(GETUTENT) extern void setutent __P((void)); diff --git a/osdef.sh b/osdef.sh index b281175..1922229 100644 --- a/osdef.sh +++ b/osdef.sh @@ -28,9 +28,7 @@ cat << EOF > osdef0.c #include #include #endif -#ifndef NAMEDPIPE #include -#endif #ifndef NOSYSLOG #include #endif diff --git a/screen.c b/screen.c index e0df6be..b796e80 100644 --- a/screen.c +++ b/screen.c @@ -418,9 +418,6 @@ int main(int ac, char** av) #ifdef SYSVSIGS debug("SYSVSIGS\n"); #endif -#ifdef NAMEDPIPE - debug("NAMEDPIPE\n"); -#endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) debug("Window size changing enabled\n"); #endif @@ -990,9 +987,6 @@ int main(int ac, char** av) attach_tty = ""; if (!detached && !lsflag && !cmdflag && !(dflag && !mflag && !rflag && !xflag) && !(sty && !SockMatch && !mflag && !rflag && !xflag)) { -#ifndef NAMEDPIPE - int fl; -#endif /* ttyname implies isatty */ SetTtyname(true, &st); @@ -1000,25 +994,11 @@ int main(int ac, char** av) tty_mode = (int)st.st_mode & 0777; #endif -#ifndef NAMEDPIPE - fl = fcntl(0, F_GETFL, 0); - if (fl != -1 && (fl & (O_RDWR|O_RDONLY|O_WRONLY)) == O_RDWR) - attach_fd = 0; -#endif - if (attach_fd == -1) { if ((n = secopen(attach_tty, O_RDWR | O_NONBLOCK, 0)) < 0) Panic(0, "Cannot open your terminal '%s' - please check.", attach_tty); - /* In case the pts device exists in another namespace we directly operate - * on the symbolic link itself. However, this means that we need to keep - * the fd open since we have no direct way of identifying the associated - * pts device accross namespaces. This is ok though since keeping fds open - * is done in the codebase already. - */ - if (attach_tty_is_in_new_ns) - attach_fd = n; - else - close(n); + /* If the server uses a socket we need an open fd. */ + attach_fd = n; } debug2("attach_tty is %s, attach_fd is %d\n", attach_tty, attach_fd); @@ -1170,6 +1150,7 @@ int main(int ac, char** av) if (lsflag) { int i, fo, oth; + bool sock; #ifdef MULTIUSER if (multi) @@ -1177,7 +1158,7 @@ int main(int ac, char** av) #endif SET_GUID(); - i = FindSocket((int *)NULL, &fo, &oth, SockMatch); + i = FindSocket((int *)NULL, &fo, &oth, SockMatch, &sock); if (quietflag) { if (rflag) exit(10 + i); @@ -1348,7 +1329,10 @@ int main(int ac, char** av) #endif sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf); - ServerSocket = MakeServerSocket(); + /* Always create sockets. We only only allow attaching to fifos not creating + * new ones. + */ + ServerSocket = MakeServerSocket(true); InitKeytab(); #ifdef ETCSCREENRC diff --git a/socket.c b/socket.c index 3472731..a249552 100644 --- a/socket.c +++ b/socket.c @@ -33,13 +33,11 @@ #include #include #include -#if !defined(NAMEDPIPE) # include # ifdef _OpenBSD_ # include # endif # include -#endif #ifndef SIGINT # include @@ -67,7 +65,7 @@ static int CheckPid __P((int)); static void ExecCreate __P((struct msg *)); static void DoCommandMsg __P((struct msg *)); -#if defined(_SEQUENT_) && !defined(NAMEDPIPE) +#if defined(_SEQUENT_) # define connect sconnect /* _SEQUENT_ has braindamaged connect */ static int sconnect __P((int, struct sockaddr *, int)); #endif @@ -122,14 +120,15 @@ extern struct comm comms[]; * If none exists or fdp is NULL SockPath is not changed. * * Returns: number of good sockets. - * + * */ int -FindSocket(fdp, nfoundp, notherp, match) +FindSocket(fdp, nfoundp, notherp, match, is_sock) int *fdp; int *nfoundp, *notherp; char *match; +bool *is_sock; { DIR *dirp; struct dirent *dp; @@ -228,21 +227,9 @@ char *match; continue; } -#ifndef SOCK_NOT_IN_FS -# ifdef NAMEDPIPE -# ifdef S_ISFIFO - debug("S_ISFIFO?\n"); - if (!S_ISFIFO(st.st_mode)) - continue; -# endif -# else -# ifdef S_ISSOCK - debug("S_ISSOCK?\n"); - if (!S_ISSOCK(st.st_mode)) + *is_sock = S_ISSOCK(st.st_mode); + if (!(*is_sock) && !S_ISFIFO(st.st_mode)) continue; -# endif -# endif -#endif debug2("st.st_uid = %d, real_uid = %d\n", st.st_uid, real_uid); #ifdef SOCKDIR /* if SOCKDIR is not defined, the socket is in $HOME. @@ -279,7 +266,7 @@ char *match; sent->next = *slisttail; *slisttail = sent; nfound++; - sent->fd = sockfd = MakeClientSocket(0); + sent->fd = sockfd = MakeClientSocket(0, *is_sock); #ifdef USE_SETEUID /* MakeClientSocket sets ids back to eff */ xseteuid(real_uid); @@ -437,217 +424,228 @@ char *match; return ngood; } +/* FIFO (legacy mode) */ +static int MakeServerFifo() +{ + register int s; + struct stat st; -/* -** -** Socket/pipe create routines -** -*/ +#ifdef USE_SETEUID + xseteuid(real_uid); + xsetegid(real_gid); +#endif + s = open(SockPath, O_WRONLY | O_NONBLOCK); + if (s >= 0) { + debug("huii, my fifo already exists??\n"); + if (quietflag) { + Kill(D_userpid, SIG_BYE); + eexit(11); + } -#ifdef NAMEDPIPE + Msg(0, "There is already a screen running on %s.", + Filename(SockPath)); -int -MakeServerSocket() -{ - register int s; - struct stat st; + if (stat(SockPath, &st) < 0) + Panic(errno, "stat"); -# ifdef USE_SETEUID - xseteuid(real_uid); - xsetegid(real_gid); -# endif - if ((s = open(SockPath, O_WRONLY | O_NONBLOCK)) >= 0) - { - debug("huii, my fifo already exists??\n"); - if (quietflag) - { - Kill(D_userpid, SIG_BYE); - eexit(11); +#ifdef SOCKDIR /* if SOCKDIR is not defined, the socket is in $HOME. \ + in that case it does not make sense to compare uids. */ + if ((int)st.st_uid != real_uid) + Panic(0, "Unfortunately you are not its owner."); +#endif + if ((st.st_mode & 0700) == 0600) + Panic(0, "To resume it, use \"screen -r\""); + else + Panic(0, "It is not detached."); + /* NOTREACHED */ } - Msg(0, "There is already a screen running on %s.", Filename(SockPath)); - if (stat(SockPath, &st) == -1) - Panic(errno, "stat"); -#ifdef SOCKDIR /* if SOCKDIR is not defined, the socket is in $HOME. - in that case it does not make sense to compare uids. */ - if ((int)st.st_uid != real_uid) - Panic(0, "Unfortunately you are not its owner."); +#ifdef USE_SETEUID + (void)unlink(SockPath); + if (mkfifo(SockPath, SOCKMODE) < 0) + Panic(0, "mkfifo %s failed", SockPath); +#ifdef BROKEN_PIPE + s = open(SockPath, O_RDWR | O_NONBLOCK, 0); +#else + s = open(SockPath, O_RDONLY | O_NONBLOCK, 0); #endif - if ((st.st_mode & 0700) == 0600) - Panic(0, "To resume it, use \"screen -r\""); - else - Panic(0, "It is not detached."); - /* NOTREACHED */ - } -# ifdef USE_SETEUID - (void) unlink(SockPath); - if (mkfifo(SockPath, SOCKMODE)) - Panic(0, "mkfifo %s failed", SockPath); -# ifdef BROKEN_PIPE - if ((s = open(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0) -# else - if ((s = open(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) -# endif - Panic(errno, "open fifo %s", SockPath); - xseteuid(eff_uid); - xsetegid(eff_gid); - return s; -# else /* !USE_SETEUID */ - if (UserContext() > 0) - { - (void) unlink(SockPath); - UserReturn(mkfifo(SockPath, SOCKMODE)); - } - if (UserStatus()) - Panic(0, "mkfifo %s failed", SockPath); -# ifdef BROKEN_PIPE - if ((s = secopen(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0) -# else - if ((s = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) -# endif - Panic(errno, "open fifo %s", SockPath); - return s; -# endif /* !USE_SETEUID */ -} + if (s < 0) + Panic(errno, "open fifo %s", SockPath); + xseteuid(eff_uid); + xsetegid(eff_gid); -int -MakeClientSocket(err) -int err; -{ - register int s = 0; + return s; - if ((s = secopen(SockPath, O_WRONLY | O_NONBLOCK, 0)) >= 0) - { - (void) fcntl(s, F_SETFL, 0); - return s; - } - if (err) - Msg(errno, "%s", SockPath); - debug2("MakeClientSocket() open %s failed (%d)\n", SockPath, errno); - return -1; +#else /* !USE_SETEUID */ + if (UserContext() > 0) { + (void)unlink(SockPath); + UserReturn(mkfifo(SockPath, SOCKMODE)); + } + if (UserStatus()) + Panic(0, "mkfifo %s failed", SockPath); +#ifdef BROKEN_PIPE + s = secopen(SockPath, O_RDWR | O_NONBLOCK, 0); +#else + s = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0); +#endif + if (s < 0) + Panic(errno, "open fifo %s", SockPath); + + return s; +#endif /* !USE_SETEUID */ } +static int MakeClientFifo(int err) +{ + register int s = 0; -#else /* NAMEDPIPE */ + s = secopen(SockPath, O_WRONLY | O_NONBLOCK, 0); + if (s >= 0) { + (void)fcntl(s, F_SETFL, 0); + return s; + } + if (err) + Msg(errno, "%s", SockPath); -int -MakeServerSocket() + return -1; +} + +/* Unix Domain Sockets */ +static int MakeServerUnixSocket() { - register int s; - struct sockaddr_un a; - struct stat st; + register int s; + struct sockaddr_un a; + struct stat st; - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - Panic(errno, "socket"); - a.sun_family = AF_UNIX; - strncpy(a.sun_path, SockPath, sizeof(a.sun_path)); - a.sun_path[sizeof(a.sun_path) - 1] = 0; -# ifdef USE_SETEUID - xseteuid(real_uid); - xsetegid(real_gid); -# endif - if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) != -1) - { - debug("oooooh! socket already is alive!\n"); - if (quietflag) - { - Kill(D_userpid, SIG_BYE); - /* - * oh, well. nobody receives that return code. papa - * dies by signal. - */ - eexit(11); - } - Msg(0, "There is already a screen running on %s.", Filename(SockPath)); - if (stat(SockPath, &st) == -1) - Panic(errno, "stat"); -#ifdef SOCKDIR /* if SOCKDIR is not defined, the socket is in $HOME. - in that case it does not make sense to compare uids. */ - if (st.st_uid != real_uid) - Panic(0, "Unfortunately you are not its owner."); + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) + Panic(errno, "socket"); + + a.sun_family = AF_UNIX; + strncpy(a.sun_path, SockPath, sizeof(a.sun_path)); + a.sun_path[sizeof(a.sun_path) - 1] = 0; + +#ifdef USE_SETEUID + xseteuid(real_uid); + xsetegid(real_gid); #endif - if ((st.st_mode & 0700) == 0600) - Panic(0, "To resume it, use \"screen -r\""); - else - Panic(0, "It is not detached."); - /* NOTREACHED */ - } + if (connect(s, (struct sockaddr *)&a, strlen(SockPath) + 2) != -1) { + debug("oooooh! socket already is alive!\n"); + if (quietflag) { + Kill(D_userpid, SIG_BYE); + /* + * oh, well. nobody receives that return code. papa + * dies by signal. + */ + eexit(11); + } + Msg(0, "There is already a screen running on %s.", + Filename(SockPath)); + + if (stat(SockPath, &st) < 0) + Panic(errno, "stat"); + +#ifdef SOCKDIR /* if SOCKDIR is not defined, the socket is in $HOME. \ + in that case it does not make sense to compare uids. */ + if (st.st_uid != real_uid) + Panic(0, "Unfortunately you are not its owner."); +#endif + if ((st.st_mode & 0700) == 0600) + Panic(0, "To resume it, use \"screen -r\""); + else + Panic(0, "It is not detached."); + /* NOTREACHED */ + } + #if defined(m88k) || defined(sysV68) - close(s); /* we get bind: Invalid argument if this is not done */ - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - Panic(errno, "reopen socket"); + close(s); /* we get bind: Invalid argument if this is not done */ + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) + Panic(errno, "reopen socket"); #endif - (void) unlink(SockPath); - if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1) - Panic(errno, "bind (%s)", SockPath); + (void)unlink(SockPath); + if (bind(s, (struct sockaddr *)&a, strlen(SockPath) + 2) == -1) + Panic(errno, "bind (%s)", SockPath); #ifdef SOCK_NOT_IN_FS - { - int f; - if ((f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE)) < 0) - Panic(errno, "shadow socket open"); - close(f); - } + { + int f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE); + if (f < 0) + Panic(errno, "shadow socket open"); + close(f); + } #else - chmod(SockPath, SOCKMODE); -# ifndef USE_SETEUID - chown(SockPath, real_uid, real_gid); -# endif + chmod(SockPath, SOCKMODE); +#ifndef USE_SETEUID + chown(SockPath, real_uid, real_gid); +#endif #endif /* SOCK_NOT_IN_FS */ - if (listen(s, 5) == -1) - Panic(errno, "listen"); -# ifdef F_SETOWN - fcntl(s, F_SETOWN, getpid()); - debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0)); -# endif /* F_SETOWN */ -# ifdef USE_SETEUID - xseteuid(eff_uid); - xsetegid(eff_gid); -# endif - return s; + if (listen(s, 5) == -1) + Panic(errno, "listen"); +#ifdef F_SETOWN + fcntl(s, F_SETOWN, getpid()); + debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0)); +#endif /* F_SETOWN */ +#ifdef USE_SETEUID + xseteuid(eff_uid); + xsetegid(eff_gid); +#endif + return s; } -int -MakeClientSocket(err) -int err; +static int MakeClientUnixSocket(int err) { - register int s; - struct sockaddr_un a; - - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - Panic(errno, "socket"); - a.sun_family = AF_UNIX; - strncpy(a.sun_path, SockPath, sizeof(a.sun_path)); - a.sun_path[sizeof(a.sun_path) - 1] = 0; -# ifdef USE_SETEUID - xseteuid(real_uid); - xsetegid(real_gid); -# else - if (access(SockPath, W_OK)) - { - if (err) - Msg(errno, "%s", SockPath); - debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno); - close(s); - return -1; - } -# endif - if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) == -1) - { - if (err) - Msg(errno, "%s: connect", SockPath); - debug("MakeClientSocket: connect failed.\n"); - close(s); - s = -1; - } -# ifdef USE_SETEUID - xseteuid(eff_uid); - xsetegid(eff_gid); -# endif - return s; + register int s; + struct sockaddr_un a; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) + Panic(errno, "socket"); + + a.sun_family = AF_UNIX; + strncpy(a.sun_path, SockPath, sizeof(a.sun_path)); + a.sun_path[sizeof(a.sun_path) - 1] = 0; +#ifdef USE_SETEUID + xseteuid(real_uid); + xsetegid(real_gid); +#else + if (access(SockPath, W_OK)) { + if (err) + Msg(errno, "%s", SockPath); + debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno); + close(s); + return -1; + } +#endif + if (connect(s, (struct sockaddr *)&a, strlen(SockPath) + 2) == -1) { + if (err) + Msg(errno, "%s: connect", SockPath); + debug("MakeClientSocket: connect failed.\n"); + close(s); + s = -1; + } +#ifdef USE_SETEUID + xseteuid(eff_uid); + xsetegid(eff_gid); +#endif + return s; +} + +int MakeServerSocket(bool socket) +{ + if (socket) + return MakeServerUnixSocket(); + + return MakeServerFifo(); } -#endif /* NAMEDPIPE */ +int MakeClientSocket(int err, bool socket) +{ + if (socket) + return MakeClientUnixSocket(err); + + return MakeClientFifo(err); +} /* ** @@ -665,6 +663,7 @@ struct NewWindow *nwin; register char *p; register int len, n; char **av = nwin->args; + bool is_socket; #ifdef NAME_MAX if (strlen(sty) > NAME_MAX) @@ -673,7 +672,8 @@ struct NewWindow *nwin; if (strlen(sty) > 2 * MAXSTR - 1) sty[2 * MAXSTR - 1] = 0; sprintf(SockPath + strlen(SockPath), "/%s", sty); - if ((s = MakeClientSocket(1)) == -1) + is_socket = IsSocket(SockPath); + if ((s = MakeClientSocket(1, is_socket)) == -1) exit(1); debug1("SendCreateMsg() to '%s'\n", SockPath); bzero((char *)&m, sizeof(m)); @@ -721,10 +721,12 @@ char *tty, *buf; { int s; struct msg m; + bool is_socket; strncpy(m.m.message, buf, sizeof(m.m.message) - 1); m.m.message[sizeof(m.m.message) - 1] = 0; - s = MakeClientSocket(0); + is_socket = IsSocket(SockPath); + s = MakeClientSocket(0, is_socket); if (s < 0) return -1; m.type = MSG_ERROR; @@ -1007,280 +1009,283 @@ struct win *wi; return 0; } -void -ReceiveMsg() +void ReceiveMsg() { - int left, len; - static struct msg m; - char *p; - int ns = ServerSocket; - struct win *wi; - int recvfd = -1; - struct acluser *user; - -#ifdef NAMEDPIPE - debug("Ha, there was someone knocking on my fifo??\n"); - if (fcntl(ServerSocket, F_SETFL, 0) == -1) - Panic(errno, "BLOCK fcntl"); - p = (char *) &m; - left = sizeof(m); -#else - struct sockaddr_un a; - struct msghdr msg; - struct iovec iov; - char control[1024]; + FILE *LLL = fopen("/tmp/zzz_rcv", "a+"); + if (LLL) { + fprintf(LLL, "asdf: %s\n", SockPath); + fprintf(LLL, "\n"); + fclose(LLL); + } - len = sizeof(a); - debug("Ha, there was someone knocking on my socket??\n"); - if ((ns = accept(ns, (struct sockaddr *) &a, (void *)&len)) < 0) - { - Msg(errno, "accept"); - return; - } + int left, len; + static struct msg m; + char *p; + int ns = ServerSocket; + struct win *wi; + int recvfd = -1; + struct acluser *user; + bool is_socket; + + /* Socket specific variables. */ + struct sockaddr_un a; + struct msghdr msg; + struct iovec iov; + char control[1024]; + + is_socket = IsSocket(SockPath); + if (!is_socket) { + debug("Ha, there was someone knocking on my fifo??\n"); + if (fcntl(ServerSocket, F_SETFL, 0) == -1) + Panic(errno, "BLOCK fcntl"); + p = (char *)&m; + left = sizeof(m); + } else { + len = sizeof(a); + debug("Ha, there was someone knocking on my socket??\n"); + if ((ns = accept(ns, (struct sockaddr *)&a, (void *)&len)) < + 0) { + Msg(errno, "accept"); + return; + } - p = (char *) &m; - left = sizeof(m); - bzero(&msg, sizeof(msg)); - iov.iov_base = &m; - iov.iov_len = left; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_controllen = sizeof(control); - msg.msg_control = &control; - while (left > 0) - { - len = recvmsg(ns, &msg, 0); - if (len < 0 && errno == EINTR) - continue; - if (len < 0) - { - close(ns); - Msg(errno, "read"); - return; - } - if (msg.msg_controllen) - { - struct cmsghdr *cmsg; - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) - { - int cl; - char *cp; - if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) - continue; - cp = (char *)CMSG_DATA(cmsg); - cl = cmsg->cmsg_len; - while(cl >= CMSG_LEN(sizeof(int))) - { - int passedfd; - bcopy(cp, &passedfd, sizeof(int)); - if (recvfd >= 0 && passedfd != recvfd) - close(recvfd); - recvfd = passedfd; - cl -= CMSG_LEN(sizeof(int)); + p = (char *)&m; + left = sizeof(m); + bzero(&msg, sizeof(msg)); + iov.iov_base = &m; + iov.iov_len = left; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_controllen = sizeof(control); + msg.msg_control = &control; + while (left > 0) { + len = recvmsg(ns, &msg, 0); + if (len < 0 && errno == EINTR) + continue; + if (len < 0) { + close(ns); + Msg(errno, "read"); + return; + } + if (msg.msg_controllen) { + struct cmsghdr *cmsg; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + int cl; + char *cp; + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + cp = (char *)CMSG_DATA(cmsg); + cl = cmsg->cmsg_len; + while (cl >= CMSG_LEN(sizeof(int))) { + int passedfd; + bcopy(cp, &passedfd, + sizeof(int)); + if (recvfd >= 0 && + passedfd != recvfd) + close(recvfd); + recvfd = passedfd; + cl -= CMSG_LEN(sizeof(int)); + } + } + } + p += len; + left -= len; + break; } - } } - p += len; - left -= len; - break; - } -#endif - - while (left > 0) - { - len = read(ns, p, left); - if (len < 0 && errno == EINTR) - continue; - if (len <= 0) - break; - p += len; - left -= len; - } + while (left > 0) { + len = read(ns, p, left); + if (len < 0 && errno == EINTR) + continue; + if (len <= 0) + break; + p += len; + left -= len; + } -#ifdef NAMEDPIPE -# ifndef BROKEN_PIPE - /* Reopen pipe to prevent EOFs at the select() call */ - close(ServerSocket); - if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) - Panic(errno, "reopen fifo %s", SockPath); - evdeq(&serv_read); - serv_read.fd = ServerSocket; - evenq(&serv_read); -# endif -#else - close(ns); + if (!is_socket) { +#ifndef BROKEN_PIPE + /* Reopen pipe to prevent EOFs at the select() call */ + close(ServerSocket); + if ((ServerSocket = + secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) + Panic(errno, "reopen fifo %s", SockPath); + evdeq(&serv_read); + serv_read.fd = ServerSocket; + evenq(&serv_read); #endif + } else { + close(ns); + } - if (len < 0) - { - Msg(errno, "read"); - if (recvfd != -1) - close(recvfd); - return; - } - if (left > 0) - { - if (left != sizeof(m)) - Msg(0, "Message %d of %d bytes too small", left, (int)sizeof(m)); - else - debug("No data on socket.\n"); - return; - } - if (m.protocol_revision != MSG_REVISION) - { - if (recvfd != -1) - close(recvfd); - Msg(0, "Invalid message (magic 0x%08x).", m.protocol_revision); - return; - } + if (len < 0) { + Msg(errno, "read"); + if (recvfd != -1) + close(recvfd); + return; + } + if (left > 0) { + if (left != sizeof(m)) + Msg(0, "Message %d of %d bytes too small", left, + (int)sizeof(m)); + else + debug("No data on socket.\n"); + return; + } + if (m.protocol_revision != MSG_REVISION) { + if (recvfd != -1) + close(recvfd); + Msg(0, "Invalid message (magic 0x%08x).", m.protocol_revision); + return; + } - debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty); - if (m.type != MSG_ATTACH && recvfd != -1) - { - close(recvfd); - recvfd = -1; - } + debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty); + if (m.type != MSG_ATTACH && recvfd != -1) { + close(recvfd); + recvfd = -1; + } - for (display = displays; display; display = display->d_next) - if (TTYCMP(D_usertty, m.m_tty) == 0) - break; - debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not "); - wi = 0; - if (!display) - { - for (wi = windows; wi; wi = wi->w_next) - if (!TTYCMP(m.m_tty, wi->w_tty)) - { - /* XXX: hmmm, rework this? */ - display = wi->w_layer.l_cvlist ? wi->w_layer.l_cvlist->c_display : 0; - debug2("but window %s %sfound.\n", m.m_tty, display ? "" : - "(backfacing)"); - break; - } - } + for (display = displays; display; display = display->d_next) + if (TTYCMP(D_usertty, m.m_tty) == 0) + break; + debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not "); + wi = 0; + if (!display) { + for (wi = windows; wi; wi = wi->w_next) + if (!TTYCMP(m.m_tty, wi->w_tty)) { + /* XXX: hmmm, rework this? */ + display = wi->w_layer.l_cvlist + ? wi->w_layer.l_cvlist->c_display + : 0; + debug2("but window %s %sfound.\n", m.m_tty, + display ? "" : "(backfacing)"); + break; + } + } - /* Remove the status to prevent garbage on the screen */ - if (display && D_status) - RemoveStatus(); + /* Remove the status to prevent garbage on the screen */ + if (display && D_status) + RemoveStatus(); - if (display && !D_tcinited && m.type != MSG_HANGUP) - { - if (recvfd != -1) - close(recvfd); - return; /* ignore messages for bad displays */ - } + if (display && !D_tcinited && m.type != MSG_HANGUP) { + if (recvfd != -1) + close(recvfd); + return; /* ignore messages for bad displays */ + } - switch (m.type) - { - case MSG_WINCH: - if (display) - CheckScreenSize(1); /* Change fore */ - break; - case MSG_CREATE: - /* - * the window that issued the create message need not be an active - * window. Then we create the window without having a display. - * Resulting in another inactive window. - */ - ExecCreate(&m); - break; - case MSG_CONT: - if (display && D_userpid != 0 && kill(D_userpid, 0) == 0) - break; /* Intruder Alert */ - debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, display ? D_userpid : 0); - /* FALLTHROUGH */ - - case MSG_ATTACH: - if (CreateTempDisplay(&m, recvfd, wi)) - break; + switch (m.type) { + case MSG_WINCH: + if (display) + CheckScreenSize(1); /* Change fore */ + break; + case MSG_CREATE: + /* + * the window that issued the create message need not be an + * active + * window. Then we create the window without having a display. + * Resulting in another inactive window. + */ + ExecCreate(&m); + break; + case MSG_CONT: + if (display && D_userpid != 0 && kill(D_userpid, 0) == 0) + break; /* Intruder Alert */ + debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, + display ? D_userpid : 0); + /* FALLTHROUGH */ + + case MSG_ATTACH: + if (CreateTempDisplay(&m, recvfd, wi)) + break; #ifdef PASSWORD - if (D_user->u_password && *D_user->u_password) - AskPassword(&m); - else + if (D_user->u_password && *D_user->u_password) + AskPassword(&m); + else #endif - FinishAttach(&m); - break; - case MSG_ERROR: - Msg(0, "%s", m.m.message); - break; - case MSG_HANGUP: - if (!wi) /* ignore hangups from inside */ - Hangup(); - break; + FinishAttach(&m); + break; + case MSG_ERROR: + Msg(0, "%s", m.m.message); + break; + case MSG_HANGUP: + if (!wi) /* ignore hangups from inside */ + Hangup(); + break; #ifdef REMOTE_DETACH - case MSG_DETACH: -# ifdef POW_DETACH - case MSG_POW_DETACH: -# endif /* POW_DETACH */ + case MSG_DETACH: +#ifdef POW_DETACH + case MSG_POW_DETACH: +#endif /* POW_DETACH */ #ifdef PASSWORD - user = *FindUserPtr(m.m.detach.duser); - if (user && user->u_password && *user->u_password) - { - if (CreateTempDisplay(&m, recvfd, 0)) - break; - AskPassword(&m); - } - else + user = *FindUserPtr(m.m.detach.duser); + if (user && user->u_password && *user->u_password) { + if (CreateTempDisplay(&m, recvfd, 0)) + break; + AskPassword(&m); + } else #endif /* PASSWORD */ - FinishDetach(&m); - break; + FinishDetach(&m); + break; #endif - case MSG_QUERY: - { - char *oldSockPath = SaveStr(SockPath); - strcpy(SockPath, m.m.command.writeback); - int s = MakeClientSocket(0); - strcpy(SockPath, oldSockPath); - Free(oldSockPath); - if (s >= 0) - { - queryflag = s; - DoCommandMsg(&m); - close(s); - } - else - queryflag = -1; - - Kill(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE); /* Send SIG_BYE if an error happened */ - queryflag = -1; + case MSG_QUERY: { + char *oldSockPath = SaveStr(SockPath); + strcpy(SockPath, m.m.command.writeback); + bool is_socket = IsSocket(SockPath); + int s = MakeClientSocket(0, is_socket); + strcpy(SockPath, oldSockPath); + Free(oldSockPath); + if (s >= 0) { + queryflag = s; + DoCommandMsg(&m); + close(s); + } else + queryflag = -1; + + Kill(m.m.command.apid, + (queryflag >= 0) + ? SIGCONT + : SIG_BYE); /* Send SIG_BYE if an error happened */ + queryflag = -1; + } break; + case MSG_COMMAND: + DoCommandMsg(&m); + break; + default: + Msg(0, "Invalid message (type %d).", m.type); } - break; - case MSG_COMMAND: - DoCommandMsg(&m); - break; - default: - Msg(0, "Invalid message (type %d).", m.type); - } } -void -ReceiveRaw(s) -int s; +void ReceiveRaw(int s) { - char rd[256]; - int len = 0; -#ifdef NAMEDPIPE - if (fcntl(s, F_SETFL, 0) == -1) - Panic(errno, "BLOCK fcntl"); -#else - struct sockaddr_un a; - len = sizeof(a); - if ((s = accept(s, (struct sockaddr *) &a, (void *)&len)) < 0) - { - Msg(errno, "accept"); - return; - } -#endif - while ((len = read(s, rd, 255)) > 0) - { - rd[len] = 0; - printf("%s", rd); - } - close(s); + char rd[256]; + int len = 0; + struct sockaddr_un a; + bool is_socket; + + is_socket = IsSocket(SockPath); + if (!is_socket) { + if (fcntl(s, F_SETFL, 0) < 0) + Panic(errno, "BLOCK fcntl"); + } else { + len = sizeof(a); + s = accept(s, (struct sockaddr *)&a, (void *)&len); + if (s < 0) { + Msg(errno, "accept"); + return; + } + } + + while ((len = read(s, rd, 255)) > 0) { + rd[len] = 0; + printf("%s", rd); + } + close(s); } -#if defined(_SEQUENT_) && !defined(NAMEDPIPE) +#if defined(_SEQUENT_) #undef connect /* * sequent_ptx socket emulation must have mode 000 on the socket! @@ -1336,6 +1341,8 @@ chsock() int RecoverSocket() { + bool is_socket; + close(ServerSocket); if ((int)geteuid() != real_uid) { @@ -1346,7 +1353,8 @@ RecoverSocket() else (void) unlink(SockPath); - if ((ServerSocket = MakeServerSocket()) < 0) + is_socket = IsSocket(SockPath); + if ((ServerSocket = MakeServerSocket(is_socket)) < 0) return 0; evdeq(&serv_read); serv_read.fd = ServerSocket; @@ -1831,8 +1839,6 @@ struct msg *mp; #endif } -#ifndef NAMEDPIPE - int SendAttachMsg(s, m, fd) int s; @@ -1871,4 +1877,12 @@ int fd; } } -#endif +bool IsSocket(const char *path) +{ + struct stat st; + + if (stat(SockPath, &st) < 0) + return false; + + return S_ISSOCK(st.st_mode); +} -- 2.11.0