📄 rshd.c
字号:
} else#endif#endif { /* child handles the original socket */ close (STDIN_FILENO); /* (0, 1, and 2 were from inetd */ close (STDOUT_FILENO); } close (STDERR_FILENO); close (pv[1]); /* close write end of pipe */ FD_ZERO (&readfrom); FD_SET (s, &readfrom); FD_SET (pv[0], &readfrom); /* set max fd + 1 for select */ if (pv[0] > s) nfd = pv[0]; else nfd = s;#ifdef ENCRYPTION#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { FD_ZERO (&writeto); FD_SET (pv2[0], &writeto); FD_SET (pv1[0], &readfrom); nfd = MAX (nfd, pv2[0]); nfd = MAX (nfd, pv1[0]); } else#endif#endif ioctl (pv[0], FIONBIO, (char *)&one); /* should set s nbio! */ nfd++; do { ready = readfrom;#ifdef ENCRYPTION#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) {#ifdef SHISHI wready = readfrom;#else wready = writeto;#endif if (select (nfd, &ready, &wready, (fd_set *) 0, (struct timeval *) 0) < 0) break; } else#endif#endif if (select (nfd, &ready, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) /* wait until something to read */ break; if (FD_ISSET (s, &ready)) { int ret;#ifdef ENCRYPTION#ifdef KERBEROS if (doencrypt) ret = des_read (s, &sig, 1); else#elif defined(SHISHI) if (doencrypt) readenc (h, s, &sig, &ret, &iv2, enckey, protocol); else#endif#endif ret = read (s, &sig, 1); if (ret <= 0) FD_CLR (s, &readfrom); else killpg (pid, sig); } if (FD_ISSET (pv[0], &ready)) { errno = 0; cc = read (pv[0], buf, sizeof buf); if (cc <= 0) { shutdown (s, 1+1); FD_CLR (pv[0], &readfrom); } else {#ifdef ENCRYPTION#ifdef KERBEROS if (doencrypt) des_write (s, buf, cc); else#elif defined(SHISHI) if (doencrypt) writeenc (h, s, buf, cc, &n, &iv4, enckey, protocol); else#endif#endif write (s, buf, cc); } }#ifdef ENCRYPTION#if defined(KERBEROS) || defined(SHISHI) if (doencrypt && FD_ISSET(pv1[0], &ready)) { errno = 0; cc = read (pv1[0], buf, sizeof(buf)); if (cc <= 0) { shutdown (pv1[0], 1+1); FD_CLR (pv1[0], &readfrom); } else#ifdef SHISHI writeenc (h, STDOUT_FILENO, buf, cc, &n, &iv3, enckey, protocol);#else des_write (STDOUT_FILENO, buf, cc);#endif } if (doencrypt && FD_ISSET(pv2[0], &wready)) { errno = 0;#ifdef SHISHI readenc (h, STDIN_FILENO, buf, &cc, &iv1, enckey, protocol);#else cc = des_read (STDIN_FILENO, buf, sizeof buf);#endif if (cc <= 0) { shutdown (pv2[0], 1+1); FD_CLR (pv2[0], &writeto); } else write (pv2[0], buf, cc); }#endif#endif } while (FD_ISSET (s, &readfrom) ||#ifdef ENCRYPTION#if defined(KERBEROS) || defined(SHISHI) (doencrypt && FD_ISSET (pv1[0], &readfrom)) ||#endif#endif FD_ISSET (pv[0], &readfrom)); /* The pipe will generat an EOR whe the shell * terminates. The socket will terninate whe the * client process terminates. */ exit (0); } /* Child process. Become a process group leader, so that * the control process above can send signals to all the * processes we may be the parent of. The process group ID * (the getpid() value below) equals the childpid value from * the fork above. */ setpgid (0, getpid ()); close(s); /* control process handles this fd */ close (pv[0]); /* close read end of pipe */#ifdef ENCRYPTION#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { close (pv1[0]); close (pv2[0]); dup2 (pv1[1], 1); dup2 (pv2[1], 0); close (pv1[1]); close (pv2[1]); }#endif#endif#if defined(SHISHI) if (use_kerberos) { int i; shishi_done (h);#ifdef ENCRYPTION if (doencrypt) { shishi_key_done (enckey); for (i = 0; i < 4; i++) { shishi_crypto_close (ivtab[i]->ctx); free (ivtab[i]->iv); } }#endif }#endif dup2 (pv[1], STDERR_FILENO); /* stderr of shell has to go pipe to control process */ close (pv[1]); } if (*pwd->pw_shell == '\0') pwd->pw_shell = PATH_BSHELL;#if BSD > 43 if (setlogin (pwd->pw_name) < 0) syslog (LOG_ERR, "setlogin() failed: %m");#endif /* Set the fid, then uid to become the user specified by "locuser" */ setegid ((gid_t)pwd->pw_gid); setgid ((gid_t)pwd->pw_gid);#ifdef HAVE_INITGROUPS initgroups (pwd->pw_name, pwd->pw_gid); /* BSD groups */#endif setuid ((uid_t)pwd->pw_uid); /* We'll execute the client's command in the home directory * of locuser. Note, that the chdir must be executed after * setuid(), otherwise it may fail on NFS mounted directories * (root mapped to nobody). */ if (chdir (pwd->pw_dir) < 0) { chdir ("/"); syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: no home directory. cmd='%.80s'", remuser, hostname, locuser, cmdbuf); rshd_error ("No remote directory.\n");#ifdef notdef exit (1);#endif } /* Set up an initial environment for the shell that we exec() */ environ = envinit; strncat (homedir, pwd->pw_dir, sizeof(homedir)-6); strcat (path, PATH_DEFPATH); strncat (shell, pwd->pw_shell, sizeof(shell)-7); strncat (username, pwd->pw_name, sizeof(username)-6); cp = strrchr (pwd->pw_shell, '/'); if (cp) cp++; /* step past first slash */ else cp = pwd->pw_shell; /* no slash in shell string */ endpwent (); if (log_success || pwd->pw_uid == 0) {#ifdef KERBEROS if (use_kerberos) syslog (LOG_INFO|LOG_AUTH, "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'", kdata->pname, kdata->pinst, kdata->prealm, hostname, locuser, cmdbuf); else#endif syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", remuser, hostname, locuser, cmdbuf); }#ifdef SHISHI if (doencrypt) execl (pwd->pw_shell, cp, "-c", cmdbuf+3, 0); else#endif execl (pwd->pw_shell, cp, "-c", cmdbuf, 0); error (1, errno, "cannot execute %s", pwd->pw_shell);}/* * Report error to client. Note: can't be used until second socket has * connected to client, or older clients will hang waiting for that * connection first. */voidrshd_error (const char *fmt, ...){ va_list ap; int len; char *bp, buf[BUFSIZ]; va_start (ap, fmt); bp = buf; if (sent_null == 0) { *bp++ = 1; len = 1; } else len = 0; vsnprintf (bp, sizeof(buf) - 1, fmt, ap); write (STDERR_FILENO, buf, len + strlen (bp));}char *getstr(const char *err){ size_t buf_len = 100; char *buf = malloc (buf_len), *end = buf; if (! buf) { rshd_error ("Out of space reading %s\n", err); exit (1); } do { /* Oh this is efficient, oh yes. [But what can be done?] */ int rd = read (STDIN_FILENO, end, 1); if (rd <= 0) { if (rd == 0) rshd_error ("EOF reading %s\n", err); else perror (err); exit (1); } end += rd; if ((buf + buf_len - end) < (buf_len >> 3)) { /* Not very much room left in our buffer, grow it. */ size_t end_offs = end - buf; buf_len += buf_len; buf = realloc (buf, buf_len); if (! buf) { rshd_error ("Out of space reading %s\n", err); exit (1); } end = buf + end_offs; } } while (*(end - 1)); return buf;}/* * Check whether host h is in our local domain, * defined as sharing the last two components of the domain part, * or the entire domain part if the local domain has only one component. * If either name is unqualified (contains no '.'), * assume that the host is local, as it will be * interpreted as such. */intlocal_domain (const char *h){ char *hostname = localhost (); if (! hostname) return 0; else { int is_local = 0; const char *p1 = topdomain (hostname); const char *p2 = topdomain (h); if (p1 == NULL || p2 == NULL || !strcasecmp (p1, p2)) is_local = 1; free (hostname); return is_local; }}const char *topdomain (const char *h){ const char *p, *maybe = NULL; int dots = 0; for (p = h + strlen(h); p >= h; p--) { if (*p == '.') { if (++dots == 2) return p; maybe = p; } } return maybe;}voidusage (){ syslog (LOG_ERR, "usage: rshd [-%s]", OPTIONS); exit (2);}voidhelp (void){ puts ("usage: rshd [options]"); puts ("\ -a, --verify-hostname Ask hostname for verification"); puts ("\ -l, --no-rhosts Ignore .rhosts file"); puts ("\ -L, --log-session Set local domain name"); puts ("\ -n, --no-keepalive Do not set SO_KEEPALIVE");#if defined(KERBEROS) || defined(SHISHI) puts ("\ -k, --kerberos Use kerberos IV authentication");#ifdef ENCRYPTION puts ("\ -x, --encrypt Use DES encryption");#endif /* ENCRYPTION */#endif /* KERBEROS */ puts ("\ -h, --help Display usage instructions"); puts ("\ -V, --version Display program version"); printf ("\nSend bug reports to %s\n", PACKAGE_BUGREPORT);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -