/[inetutils]/inetutils/rexecd/rexecd.c
ViewVC logotype

Diff of /inetutils/rexecd/rexecd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.25 by ams, Fri Jan 21 07:54:52 2005 UTC revision 1.26 by ams, Thu Sep 22 09:03:24 2005 UTC
# Line 28  Line 28 
28   */   */
29    
30  #ifndef lint  #ifndef lint
31  static char copyright[] =  static char copyright[] = "@(#) Copyright (c) 1983, 1993\n\
 "@(#) Copyright (c) 1983, 1993\n\  
32          The Regents of the University of California.  All rights reserved.\n";          The Regents of the University of California.  All rights reserved.\n";
33  #endif /* not lint */  #endif /* not lint */
34    
# Line 70  static char sccsid[] = "@(#)rexecd.c   8.1 Line 69  static char sccsid[] = "@(#)rexecd.c   8.1
69  #include <string.h>  #include <string.h>
70  #include <unistd.h>  #include <unistd.h>
71  #include <crypt.h>  #include <crypt.h>
72    #include <getopt.h>
73  #ifdef HAVE_SYS_SELECT_H  #ifdef HAVE_SYS_SELECT_H
74  #include <sys/select.h>  #include <sys/select.h>
75  #endif  #endif
# Line 83  static char sccsid[] = "@(#)rexecd.c   8.1 Line 83  static char sccsid[] = "@(#)rexecd.c   8.1
83  #endif  #endif
84    
85  void error __P ((const char *fmt, ...));  void error __P ((const char *fmt, ...));
86    void usage (void);
87    
88    static const char *short_options = "hV";
89    static struct option long_options[] = {
90      {"help", no_argument, 0, 'h'},
91      {"version", no_argument, 0, 'V'},
92      {0}
93    };
94    
95  /*  /*
96   * remote execute server:   * remote execute server:
97   *      username\0   *      username\0
# Line 92  void error __P ((const char *fmt, ...)); Line 101  void error __P ((const char *fmt, ...));
101   */   */
102  /*ARGSUSED*/  /*ARGSUSED*/
103  int  int
104  main(int argc, char **argv)  main (int argc, char **argv)
105  {  {
106          struct sockaddr_in from;    struct sockaddr_in from;
107          int fromlen, sockfd = STDIN_FILENO;    int fromlen, sockfd = STDIN_FILENO;
108      int c;
109          fromlen = sizeof (from);  
110          if (getpeername(sockfd, (struct sockaddr *)&from, &fromlen) < 0) {    while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
111                  fprintf(stderr,           != EOF)
112                          "rexecd: getpeername: %s\n", strerror(errno));      {
113                  exit(1);        switch (c)
114            {
115            case 'V':
116              printf ("rexecd (%s %s)\n", PACKAGE_NAME, PACKAGE_VERSION);
117              exit (0);
118    
119            case 'h':
120            default:
121              usage ();
122              exit (0);
123          }          }
124          doit(sockfd, &from);      }
125          exit (0);  
126      fromlen = sizeof (from);
127      if (getpeername (sockfd, (struct sockaddr *) &from, &fromlen) < 0)
128        {
129          fprintf (stderr, "rexecd: getpeername: %s\n", strerror (errno));
130          exit (1);
131        }
132      doit (sockfd, &from);
133      exit (0);
134  }  }
135    
136  char    username[20] = "USER=";  char username[20] = "USER=";
137  char    logname[23] = "LOGNAME=";  char logname[23] = "LOGNAME=";
138  char    homedir[64] = "HOME=";  char homedir[64] = "HOME=";
139  char    shell[64] = "SHELL=";  char shell[64] = "SHELL=";
140  char    path[sizeof(PATH_DEFPATH) + sizeof("PATH=")] = "PATH=";  char path[sizeof (PATH_DEFPATH) + sizeof ("PATH=")] = "PATH=";
141  char    *envinit[] =  char *envinit[] = { homedir, shell, path, username, logname, 0 };
142              {homedir, shell, path, username, logname, 0};  extern char **environ;
 extern char     **environ;  
143    
144  #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN  #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
145  struct  sockaddr_in asin = { sizeof(asin), AF_INET };  struct sockaddr_in asin = { sizeof (asin), AF_INET };
146  #else  #else
147  struct  sockaddr_in asin = { AF_INET };  struct sockaddr_in asin = { AF_INET };
148  #endif  #endif
149    
150  char *getstr __P ((const char *));  char *getstr __P ((const char *));
151    
152  static char *  static char *
153  get_user_password(struct passwd *pwd)  get_user_password (struct passwd *pwd)
154  {  {
155    char *pw_text = pwd->pw_passwd;    char *pw_text = pwd->pw_passwd;
156  #ifdef HAVE_SHADOW_H  #ifdef HAVE_SHADOW_H
157    struct spwd *spwd = getspnam(pwd->pw_name);    struct spwd *spwd = getspnam (pwd->pw_name);
158    if (spwd)    if (spwd)
159      pw_text = spwd->sp_pwdp;      pw_text = spwd->sp_pwdp;
160  #endif  #endif
# Line 137  get_user_password(struct passwd *pwd) Line 162  get_user_password(struct passwd *pwd)
162  }  }
163    
164  int  int
165  doit(int f, struct sockaddr_in *fromp)  doit (int f, struct sockaddr_in *fromp)
166  {  {
167          char *cmdbuf, *cp, *namep;    char *cmdbuf, *cp, *namep;
168          char *user, *pass, *pw_password;    char *user, *pass, *pw_password;
169          struct passwd *pwd;    struct passwd *pwd;
170          int s;    int s;
171          u_short port;    u_short port;
172          int pv[2], pid, cc;    int pv[2], pid, cc;
173          fd_set readfrom, ready;    fd_set readfrom, ready;
174          char buf[BUFSIZ], sig;    char buf[BUFSIZ], sig;
175          int one = 1;    int one = 1;
176    
177          signal(SIGINT, SIG_DFL);    signal (SIGINT, SIG_DFL);
178          signal(SIGQUIT, SIG_DFL);    signal (SIGQUIT, SIG_DFL);
179          signal(SIGTERM, SIG_DFL);    signal (SIGTERM, SIG_DFL);
180  #ifdef DEBUG  #ifdef DEBUG
181          { int t = open(_PATH_TTY, O_RDWR);    {
182            if (t >= 0) {      int t = open (_PATH_TTY, O_RDWR);
183                  ioctl(t, TIOCNOTTY, (char *)0);      if (t >= 0)
184                  close(t);        {
185            }          ioctl (t, TIOCNOTTY, (char *) 0);
186            close (t);
187          }
188      }
189    #endif
190      if (f != STDIN_FILENO)
191        {
192          dup2 (f, STDIN_FILENO);
193          dup2 (f, STDOUT_FILENO);
194          dup2 (f, STDERR_FILENO);
195        }
196    
197      alarm (60);
198      port = 0;
199      for (;;)
200        {
201          char c;
202          if (read (f, &c, 1) != 1)
203            exit (1);
204          if (c == 0)
205            break;
206          port = port * 10 + c - '0';
207        }
208      alarm (0);
209      if (port != 0)
210        {
211          s = socket (AF_INET, SOCK_STREAM, 0);
212          if (s < 0)
213            exit (1);
214          if (bind (s, (struct sockaddr *) &asin, sizeof (asin)) < 0)
215            exit (1);
216          alarm (60);
217          fromp->sin_port = htons (port);
218          if (connect (s, (struct sockaddr *) fromp, sizeof (*fromp)) < 0)
219            exit (1);
220          alarm (0);
221        }
222    
223      user = getstr ("username");
224      pass = getstr ("password");
225      cmdbuf = getstr ("command");
226    
227      setpwent ();
228      pwd = getpwnam (user);
229      if (pwd == NULL)
230        {
231          error ("Login incorrect.\n");
232          exit (1);
233        }
234      endpwent ();
235      pw_password = get_user_password (pwd);
236      if (*pw_password != '\0')
237        {
238          namep = crypt (pass, pw_password);
239          if (strcmp (namep, pw_password))
240            {
241              error ("Password incorrect.\n");
242              exit (1);
243          }          }
244  #endif      }
245          if (f != STDIN_FILENO) {    write (STDERR_FILENO, "\0", 1);
246              dup2(f, STDIN_FILENO);    if (port)
247              dup2(f, STDOUT_FILENO);      {
248              dup2(f, STDERR_FILENO);        pipe (pv);
249          pid = fork ();
250          if (pid == -1)
251            {
252              error ("Try again.\n");
253              exit (1);
254          }          }
255          if (pid)
256          alarm(60);          {
257          port = 0;            close (STDIN_FILENO);
258          for (;;) {            close (STDOUT_FILENO);
259                  char c;            close (STDERR_FILENO);
260                  if (read(f, &c, 1) != 1)            close (f);
261                          exit(1);            close (pv[1]);
262                  if (c == 0)            FD_ZERO (&readfrom);
263                          break;            FD_SET (s, &readfrom);
264                  port = port * 10 + c - '0';            FD_SET (pv[0], &readfrom);
265          }            ioctl (pv[1], FIONBIO, (char *) &one);
266          alarm(0);            /* should set s nbio! */
267          if (port != 0) {            do
268                  s = socket(AF_INET, SOCK_STREAM, 0);              {
269                  if (s < 0)                int maxfd = s;
270                          exit(1);                ready = readfrom;
271                  if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0)                if (pv[0] > maxfd)
272                          exit(1);                  maxfd = pv[0];
273                  alarm(60);                select (maxfd + 1, (fd_set *) & ready,
274                  fromp->sin_port = htons(port);                        (fd_set *) NULL, (fd_set *) NULL,
275                  if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0)                        (struct timeval *) NULL);
276                          exit(1);                if (FD_ISSET (s, &ready))
277                  alarm(0);                  {
278          }                    if (read (s, &sig, 1) <= 0)
279                        FD_CLR (s, &readfrom);
280          user = getstr ("username");                    else
281          pass = getstr ("password");                      killpg (pid, sig);
         cmdbuf = getstr ("command");  
   
         setpwent();  
         pwd = getpwnam(user);  
         if (pwd == NULL) {  
                 error("Login incorrect.\n");  
                 exit(1);  
         }  
         endpwent();  
         pw_password = get_user_password(pwd);  
         if (*pw_password != '\0') {  
                 namep = crypt (pass, pw_password);  
                 if (strcmp(namep, pw_password)) {  
                         error("Password incorrect.\n");  
                         exit(1);  
282                  }                  }
283          }                if (FD_ISSET (pv[0], &ready))
284          write(STDERR_FILENO, "\0", 1);                  {
285          if (port) {                    cc = read (pv[0], buf, sizeof (buf));
286                  pipe(pv);                    if (cc <= 0)
287                  pid = fork();                      {
288                  if (pid == -1)  {                        shutdown (s, 1 + 1);
289                          error("Try again.\n");                        FD_CLR (pv[0], &readfrom);
290                          exit(1);                      }
291                      else
292                        write (s, buf, cc);
293                  }                  }
294                  if (pid) {              }
295                          close(STDIN_FILENO);            while (FD_ISSET (pv[0], &readfrom) || FD_ISSET (s, &readfrom));
296                          close(STDOUT_FILENO);            exit (0);
                         close(STDERR_FILENO);  
                         close(f); close(pv[1]);  
                         FD_ZERO(&readfrom);  
                         FD_SET(s, &readfrom);  
                         FD_SET(pv[0], &readfrom);  
                         ioctl(pv[1], FIONBIO, (char *)&one);  
                         /* should set s nbio! */  
                         do {  
                                 int maxfd = s;  
                                 ready = readfrom;  
                                 if (pv[0] > maxfd)  
                                     maxfd = pv[0];  
                                 select(maxfd + 1, (fd_set *)&ready,  
                                     (fd_set *)NULL, (fd_set *)NULL,  
                                     (struct timeval *)NULL);  
                                 if (FD_ISSET(s, &ready)) {  
                                         if (read(s, &sig, 1) <= 0)  
                                                 FD_CLR(s, &readfrom);  
                                         else  
                                                 killpg(pid, sig);  
                                 }  
                                 if (FD_ISSET(pv[0], &ready)) {  
                                         cc = read(pv[0], buf, sizeof (buf));  
                                         if (cc <= 0) {  
                                                 shutdown(s, 1+1);  
                                                 FD_CLR(pv[0], &readfrom);  
                                         } else  
                                                 write(s, buf, cc);  
                                 }  
                         } while (FD_ISSET(pv[0], &readfrom) ||  
                                 FD_ISSET(s, &readfrom));  
                         exit(0);  
                 }  
                 setpgid (0, getpid());  
                 close(s);  
                 close(pv[0]);  
                 dup2(pv[1], STDERR_FILENO);  
297          }          }
298          if (*pwd->pw_shell == '\0')        setpgid (0, getpid ());
299                  pwd->pw_shell = PATH_BSHELL;        close (s);
300          if (f > 2)        close (pv[0]);
301                  close(f);        dup2 (pv[1], STDERR_FILENO);
302          setegid((gid_t)pwd->pw_gid);      }
303          setgid((gid_t)pwd->pw_gid);    if (*pwd->pw_shell == '\0')
304        pwd->pw_shell = PATH_BSHELL;
305      if (f > 2)
306        close (f);
307      setegid ((gid_t) pwd->pw_gid);
308      setgid ((gid_t) pwd->pw_gid);
309  #ifdef HAVE_INITGROUPS  #ifdef HAVE_INITGROUPS
310          initgroups(pwd->pw_name, pwd->pw_gid);    initgroups (pwd->pw_name, pwd->pw_gid);
311  #endif  #endif
312          setuid((uid_t)pwd->pw_uid);    setuid ((uid_t) pwd->pw_uid);
313          if (chdir(pwd->pw_dir) < 0) {    if (chdir (pwd->pw_dir) < 0)
314                  error("No remote directory.\n");      {
315                  exit(1);        error ("No remote directory.\n");
316          }        exit (1);
317          strcat(path, PATH_DEFPATH);      }
318          environ = envinit;    strcat (path, PATH_DEFPATH);
319          strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);    environ = envinit;
320          strncat(shell, pwd->pw_shell, sizeof(shell)-7);    strncat (homedir, pwd->pw_dir, sizeof (homedir) - 6);
321          strncat(username, pwd->pw_name, sizeof(username)-6);    strncat (shell, pwd->pw_shell, sizeof (shell) - 7);
322          cp = strrchr(pwd->pw_shell, '/');    strncat (username, pwd->pw_name, sizeof (username) - 6);
323          if (cp)    cp = strrchr (pwd->pw_shell, '/');
324                  cp++;    if (cp)
325          else      cp++;
326                  cp = pwd->pw_shell;    else
327          execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);      cp = pwd->pw_shell;
328          perror(pwd->pw_shell);    execl (pwd->pw_shell, cp, "-c", cmdbuf, 0);
329          exit(1);    perror (pwd->pw_shell);
330      exit (1);
331  }  }
332    
333  /*VARARGS1*/  /*VARARGS1*/
334  void  void
335  error(const char *fmt, ...)  error (const char *fmt, ...)
336  {  {
337    va_list ap;    va_list ap;
338    int len;    int len;
339    char buf[BUFSIZ];    char buf[BUFSIZ];
340  #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__  #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
341          va_start(ap, fmt);    va_start (ap, fmt);
342  #else  #else
343          va_start(ap);    va_start (ap);
344  #endif  #endif
345    buf[0] = 1;    buf[0] = 1;
346    snprintf (buf + 1, sizeof buf - 1, fmt, ap);    snprintf (buf + 1, sizeof buf - 1, fmt, ap);
347    write (STDERR_FILENO, buf, strlen(buf));    write (STDERR_FILENO, buf, strlen (buf));
348  }  }
349    
350  char *  char *
351  getstr(const char *err)  getstr (const char *err)
352  {  {
353          size_t buf_len = 100;    size_t buf_len = 100;
354          char *buf = malloc (buf_len), *end = buf;    char *buf = malloc (buf_len), *end = buf;
355    
356          if (! buf) {    if (!buf)
357                  error ("Out of space reading %s\n", err);      {
358                  exit (1);        error ("Out of space reading %s\n", err);
359          exit (1);
360        }
361    
362      do
363        {
364          /* Oh this is efficient, oh yes.  [But what can be done?] */
365          int rd = read (STDIN_FILENO, end, 1);
366          if (rd <= 0)
367            {
368              if (rd == 0)
369                error ("EOF reading %s\n", err);
370              else
371                perror (err);
372              exit (1);
373          }          }
374    
375          do {        end += rd;
376                  /* Oh this is efficient, oh yes.  [But what can be done?] */        if ((buf + buf_len - end) < (buf_len >> 3))
377                  int rd = read(STDIN_FILENO, end, 1);          {
378                  if (rd <= 0) {            /* Not very much room left in our buffer, grow it. */
379                          if (rd == 0)            size_t end_offs = end - buf;
380                                  error ("EOF reading %s\n", err);            buf_len += buf_len;
381                          else            buf = realloc (buf, buf_len);
382                                  perror (err);            if (!buf)
383                          exit(1);              {
384                  }                error ("Out of space reading %s\n", err);
385                  exit (1);
386                }
387              end = buf + end_offs;
388            }
389        }
390      while (*(end - 1));
391    
392                  end += rd;    return buf;
393                  if ((buf + buf_len - end) < (buf_len >> 3)) {  }
394                          /* Not very much room left in our buffer, grow it. */  
395                          size_t end_offs = end - buf;  
396                          buf_len += buf_len;  static const char usage_str[] =
397                          buf = realloc (buf, buf_len);    "Usage: rexecd [OPTIONS...]\n"
398                          if (! buf) {    "\n"
399                                  error ("Out of space reading %s\n", err);    "Options are:\n"
400                                  exit (1);    "       --help              Display usage instructions\n"
401                          }    "       --version           Display program version\n";
                         end = buf + end_offs;  
                 }  
         } while (*(end - 1));  
402    
403          return buf;  void
404    usage (void)
405    {
406      printf ("%s\n" "Send bug reports to <%s>\n", usage_str, PACKAGE_BUGREPORT);
407  }  }

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.26

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26