📄 rshd.c
字号:
* to it, plus. */ int lport = IPPORT_RESERVED - 1; s = rresvport (&lport); if (s < 0) { syslog (LOG_ERR, "can't get stderr port: %m"); exit (1); }#if defined(KERBEROS) || defined(SHISHI) if (!use_kerberos)#endif if (port >= IPPORT_RESERVED || port < IPPORT_RESERVED/2) { syslog (LOG_ERR, "2nd port not reserved\n"); exit (1); } /* Use the fromp structure taht we already have. * The 32-bit Internet address is obviously that of the * client's, just change the port# to the one specified * by the clent as the secondary port. */ syslog (LOG_ERR, "2nd port not reserved %d\n", port); fromp->sin_port = htons (port); if (connect (s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { syslog (LOG_INFO, "connect second port %d: %m", port); exit (1); } }#if defined(KERBEROS) || defined(SHISHI) if (vacuous) { rshd_error ("rshd: remote host requires Kerberos authentication\n"); exit (1); }#endif /* from inetd, socket is already on 0, 1, 2 */ if (sockfd != STDIN_FILENO) { dup2 (sockfd, STDIN_FILENO); dup2 (sockfd, STDOUT_FILENO); dup2 (sockfd, STDERR_FILENO); } /* Get the "name" of the client from its Internet address. This is * used for the authentication below. */ errorstr = NULL; hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), fromp->sin_family); if (hp) { /* * If name returned by gethostbyaddr is in our domain, * attempt to verify that we haven't been fooled by someone * in a remote net; look up the name and check that this * address corresponds to the name. */ hostname = strdup (hp->h_name);#if defined(KERBEROS) || defined(SHISHI) if (!use_kerberos)#endif if (check_all || local_domain (hp->h_name)) { char *remotehost = (char *) alloca (strlen (hostname) + 1); if (! remotehost) errorstr = "Out of memory\n"; else { strcpy (remotehost, hostname); errorhost = remotehost; hp = gethostbyname (remotehost); if (hp == NULL) { syslog (LOG_INFO, "Couldn't look up address for %s", remotehost); errorstr = "Couldn't look up address for your host (%s)\n"; hostname = inet_ntoa (fromp->sin_addr); } else for (; ; hp->h_addr_list++) { if (hp->h_addr_list[0] == NULL) { syslog (LOG_NOTICE, "Host addr %s not listed for host %s", inet_ntoa (fromp->sin_addr), hp->h_name); errorstr = "Host address mismatch for %s\n"; hostname = inet_ntoa (fromp->sin_addr); break; } if (!memcmp (hp->h_addr_list[0], (caddr_t)&fromp->sin_addr, sizeof fromp->sin_addr)) { hostname = hp->h_name; break; /* equal, OK */ } } } } } else errorhost = hostname = inet_ntoa (fromp->sin_addr);#ifdef KERBEROS if (use_kerberos) { kdata = (AUTH_DAT *) authbuf; ticket = (KTEXT) tickbuf; authopts = 0L; strcpy (instance, "*"); version[VERSION_SIZE - 1] = '\0';#ifdef ENCRYPTION if (doencrypt) { struct sockaddr_in local_addr; rc = sizeof local_addr; if (getsockname (STDIN_FILENO, (struct sockaddr *)&local_addr, &rc) < 0) { syslog (LOG_ERR, "getsockname: %m"); rshd_error ("rlogind: getsockname: %s", strerror (errno)); exit (1); } authopts = KOPT_DO_MUTUAL; rc = krb_recvauth (authopts, 0, ticket, "rcmd", instance, &fromaddr, &local_addr, kdata, "", schedule, version); des_set_key (kdata->session, schedule); } else#endif rc = krb_recvauth (authopts, 0, ticket, "rcmd", instance, &fromaddr, (struct sockaddr_in *) 0, kdata, "", (bit_64 *) 0, version); if (rc != KSUCCESS) { rshd_error ("Kerberos authentication failure: %s\n", krb_err_txt[rc]); exit (1); } } else#elif defined (SHISHI) if (use_kerberos) { int rc; char *err_msg; rc = get_auth (STDIN_FILENO, &h, &ap, &enckey, &err_msg, &protocol, &cksumtype, &cksum, &cksumlen); if (rc != SHISHI_OK) { rshd_error ("Kerberos authentication failure: %s\n", err_msg ? err_msg : shishi_strerror (rc)); exit (1); } } else#endif remuser = getstr ("remuser"); /* Read three strings from the client. */ locuser = getstr ("locuser"); cmdbuf = getstr ("command");#ifdef SHISHI { int error; int rc; char * compcksum; size_t compcksumlen; char cksumdata[100]; struct sockaddr_in sock; size_t socklen; #ifdef ENCRYPTION if (strlen (cmdbuf) >= 3) if (!strncmp (cmdbuf, "-x ", 3)) { doencrypt = 1; int i; ivtab[0] = &iv1; ivtab[1] = &iv2; ivtab[2] = &iv3; ivtab[3] = &iv4; keytype = shishi_key_type (enckey); keylen = shishi_cipher_blocksize (keytype); for (i=0; i<4; i++) { ivtab[i]->ivlen = keylen; switch (keytype) { case SHISHI_DES_CBC_CRC: case SHISHI_DES_CBC_MD4: case SHISHI_DES_CBC_MD5: case SHISHI_DES_CBC_NONE: case SHISHI_DES3_CBC_HMAC_SHA1_KD: ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; ivtab[i]->iv = malloc (ivtab[i]->ivlen); memset (ivtab[i]->iv, 2*i -3*(i>=2), ivtab[i]->ivlen); ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), ivtab[i]->iv, ivtab[i]->ivlen); break; case SHISHI_ARCFOUR_HMAC: case SHISHI_ARCFOUR_HMAC_EXP: ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 4*(i<2) + 2 + 2*(i%2); ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), NULL, 0); break; default : ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 4*(i<2) + 2 + 2*(i%2); ivtab[i]->iv = malloc (ivtab[i]->ivlen); memset (ivtab[i]->iv, 0, ivtab[i]->ivlen); if (protocol == 2) ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), ivtab[i]->iv, ivtab[i]->ivlen); } } }#endif remuser = getstr ("remuser"); rc = read (STDIN_FILENO, &error, sizeof (int)); if ((rc != sizeof (int)) && rc) exit (1); /* verify checksum */ /* Doesn't give socket port ? if (getsockname (STDIN_FILENO, (struct sockaddr *)&sock, &socklen) < 0) { syslog (LOG_ERR, "Can't get sock name"); exit (1); } */ snprintf (cksumdata, 100, "544:%s%s", /*ntohs(sock.sin_port),*/ cmdbuf, locuser); rc = shishi_checksum (h, enckey, 0, cksumtype, cksumdata, strlen (cksumdata), &compcksum, &compcksumlen); free (cksum); if (rc != SHISHI_OK || compcksumlen != cksumlen || memcmp (compcksum, cksum, cksumlen) != 0) { /* err_msg crash ? */ /* *err_msg = "checksum verify failed"; */ syslog (LOG_ERR, "checksum verify failed: %s", shishi_error (h)); free (compcksum); exit (1); } rc = shishi_authorized_p (h, shishi_ap_tkt (ap), locuser); if (!rc) { syslog (LOG_ERR, "User is not authorized to log in as: %s", locuser); shishi_ap_done (ap); exit (1); } free (compcksum); shishi_ap_done (ap); }#endif /* Look up locuser in the passerd file. The locuser has\* to be a * valid account on this system. */ setpwent (); pwd = getpwnam (locuser); if (pwd == NULL) { syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: unknown login. cmd='%.80s'", remuser, hostname, locuser, cmdbuf); if (errorstr == NULL) errorstr = "Login incorrect.\n"; goto fail; }#ifdef KERBEROS if (use_kerberos) { if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { if (kuserok (kdata, locuser) != 0) { syslog (LOG_INFO|LOG_AUTH, "Kerberos rsh denied to %s.%s@%s", kdata->pname, kdata->pinst, kdata->prealm); rshd_error ("Permission denied.\n"); exit (1); } } } else#elif defined(SHISHI) if (use_kerberos) {/* if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { if (kuserok (kdata, locuser) != 0) { syslog (LOG_INFO|LOG_AUTH, "Kerberos rsh denied to %s.%s@%s", kdata->pname, kdata->pinst, kdata->prealm); rshd_error ("Permission denied.\n"); exit (1); } }*/ } else#endif if (errorstr || pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && (iruserok (fromp->sin_addr.s_addr, pwd->pw_uid == 0, remuser, locuser)) < 0) { if (__rcmd_errstr) syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: permission denied (%s). cmd='%.80s'", remuser, hostname, locuser, __rcmd_errstr, cmdbuf); else syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: permission denied. cmd='%.80s'", remuser, hostname, locuser, cmdbuf); fail: if (errorstr == NULL) errorstr = "Permission denied.\n"; rshd_error (errorstr, errorhost); exit (1); } /* If the locuser isn't root, then check if logins are disabled. */ if (pwd->pw_uid && !access (PATH_NOLOGIN, F_OK)) { rshd_error ("Logins currently disabled.\n"); exit (1); } /* Now write the null byte back to the client telling it * that everything is OK. * Note that this means that any error message that we generate * from now on (such as the perror() if the execl() fails), won't * be seen by the rcomd() fucntion, but will be seen by the * application that called rcmd() when it reads from the socket. */ if (write (STDERR_FILENO, "\0", 1) < 0) { rshd_error ("Lost connection.\n"); exit (1); } sent_null = 1; if (port) { /* We nee a secondary channel, Here's where we create * the control process that'll handle this secondary * channel. * First create a pipe to use for communication between * the parent and child, then fork. */ if (pipe (pv) < 0) { rshd_error ("Can't make pipe.\n"); exit (1); }#ifdef ENCRYPTION#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { if (pipe (pv1) < 0) { rshd_error ("Can't make 2nd pipe.\n"); exit (1); } if (pipe (pv2) < 0) { rshd_error ("Can't make 3rd pipe.\n"); exit (1); } }#endif#endif pid = fork (); if (pid == -1) { rshd_error ("Can't fork; try again.\n"); exit (1); } if (pid) { /* Parent process == control process. * We: (1) read from the pipe and write to s; * (2) read from s and send corresponding * signal. */#ifdef ENCRYPTION#if defined(KERBEROS) if (doencrypt) { static char msg[] = SECURE_MESSAGE; close (pv1[1]); close (pv2[1]); des_write (s, msg, sizeof(msg) - 1); } else#elif defined(SHISHI) if (doencrypt) { close (pv1[1]); close (pv2[1]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -