📄 rlogind.c
字号:
if (verify_hostname || in_local_domain (ap->hostname)) { int match = 0; for (hp = gethostbyname (ap->hostname); hp && !match; hp->h_addr_list++) { if (hp->h_addr_list[0] == NULL) break; match = memcmp (hp->h_addr_list[0], &ap->from.sin_addr, sizeof (ap->from.sin_addr)) == 0; } if (!match) { syslog (LOG_ERR | LOG_AUTH, "cannot find matching IP for %s (%s)", ap->hostname, inet_ntoa (ap->from.sin_addr)); fatal (fd, "Permission denied", 0); } }#if defined(KERBEROS) || defined(SHISHI) if (kerberos) { const char *err_msg; int c = 0; if (do_krb_login (fd, ap, &err_msg) == 0) authenticated++; else fatal (fd, err_msg, 0); write (fd, &c, 1); confirmed = 1; /* we sent the null! */ } else#endif { int port = ntohs (ap->from.sin_port); if (ap->from.sin_family != AF_INET || port >= IPPORT_RESERVED || port < IPPORT_RESERVED / 2) { syslog (LOG_NOTICE, "Connection from %s on illegal port %d", inet_ntoa (ap->from.sin_addr), port); fatal (fd, "Permission denied", 0); }#ifdef IP_OPTIONS { u_char optbuf[BUFSIZ / 3], *cp; char lbuf[BUFSIZ], *lp; int optsize = sizeof (optbuf), ipproto; struct protoent *ip; if ((ip = getprotobyname ("ip")) != NULL) ipproto = ip->p_proto; else ipproto = IPPROTO_IP; if (getsockopt (0, ipproto, IP_OPTIONS, (char *) optbuf, &optsize) == 0 && optsize != 0) { lp = lbuf; for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) sprintf (lp, " %2.2x", *cp); syslog (LOG_NOTICE, "Ignoring IP options: %s", lbuf); if (setsockopt (0, ipproto, IP_OPTIONS, (char *) NULL, optsize)) { syslog (LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); exit (1); } } }#endif /* IP_OPTIONS */ if (do_rlogin (fd, ap) == 0) authenticated++; } if (confirmed == 0) { write (fd, "", 1); confirmed = 1; /* we sent the null! */ }#ifdef SHISHI len = sizeof (SECURE_MESSAGE) - 1; IF_ENCRYPT (writeenc (ap->h, fd, SECURE_MESSAGE, len, &c, &ap->iv2, ap->enckey, ap->protocol));#else IF_ENCRYPT (des_write (fd, SECURE_MESSAGE, sizeof (SECURE_MESSAGE) - 1));#endif return authenticated;}voidsetup_tty (int fd, struct auth_data *ap){ register char *cp = strchr (ap->term + ENVSIZE, '/'); char *speed; struct termios tt; tcgetattr (fd, &tt); if (cp) { *cp++ = '\0'; speed = cp; cp = strchr (speed, '/'); if (cp) *cp++ = '\0';#ifdef HAVE_CFSETSPEED cfsetspeed (&tt, strtoul (speed, NULL, 10));#else cfsetispeed (&tt, strtoul (speed, NULL, 10)); cfsetospeed (&tt, strtoul (speed, NULL, 10));#endif } tt.c_iflag = TTYDEF_IFLAG; tt.c_oflag = TTYDEF_OFLAG; tt.c_lflag = TTYDEF_LFLAG; tcsetattr (fd, TCSAFLUSH, &tt); ap->env[0] = ap->term; ap->env[1] = 0;}#ifdef UTMPXchar *utmp_ptsid ();/*FIXME*/ void utmp_init ();voidsetup_utmp (char *line){ char *ut_id = utmp_ptsid (line, "rl"); utmp_init (line + sizeof ("/dev/") - 1, ".rlogin", ut_id);}#else# define setup_utmp(line)#endifvoidexec_login (int authenticated, struct auth_data *ap){ if (authenticated) {#ifdef SOLARIS execle (path_login, "login", "-p", "-h", ap->hostname, ap->term, "-f", "--", ap->lusername, NULL, ap->env);#else execle (path_login, "login", "-p", "-h", ap->hostname, "-f", ap->lusername, NULL, ap->env);#endif } else {#ifdef SOLARIS execle (path_login, "login", "-p", "-h", ap->hostname, ap->term, "--", ap->lusername, NULL, ap->env);#else execle (path_login, "login", "-p", "-h", ap->hostname, ap->lusername, NULL, ap->env);#endif } syslog (LOG_ERR, "can't exec login: %m");}intrlogind_mainloop (int infd, int outfd){ size_t size; struct auth_data auth_data; int true; char c; int authenticated; pid_t pid; int master; memset (&auth_data, 0, sizeof auth_data); size = sizeof auth_data.from; if (getpeername (infd, (struct sockaddr *) &auth_data.from, &size) < 0) { syslog (LOG_ERR, "Can't get peer name of remote host: %m"); fatal (outfd, "Can't get peer name of remote host", 1); } syslog (LOG_INFO, "Connect from %s:%d", inet_ntoa (auth_data.from.sin_addr), ntohs (auth_data.from.sin_port)); true = 1; if (keepalive && setsockopt (infd, SOL_SOCKET, SO_KEEPALIVE, &true, sizeof true) < 0) syslog (LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");#if defined (IP_TOS) && defined (IPPROTO_IP) && defined (IPTOS_LOWDELAY) true = IPTOS_LOWDELAY; if (setsockopt (infd, IPPROTO_IP, IP_TOS, (char *) &true, sizeof true) < 0) syslog (LOG_WARNING, "setsockopt (IP_TOS): %m");#endif alarm (60); /* Wait at most 60 seconds. FIXME: configurable? */ /* Read the null byte */ if (read (infd, &c, 1) != 1 || c != 0) { syslog (LOG_CRIT, "protocol error: expected 0 byte"); exit (1); } alarm (0); authenticated = rlogind_auth (infd, &auth_data); pid = forkpty (&master, line, NULL, &win); if (pid < 0) { if (errno == ENOENT) { syslog (LOG_ERR, "Out of ptys"); fatal (infd, "Out of ptys", 0); } else { syslog (LOG_ERR, "forkpty: %m"); fatal (infd, "Forkpty", 1); } } if (pid == 0) { /* Child */ if (infd > 2) close (infd); setup_tty (0, &auth_data); setup_utmp (line); exec_login (authenticated, &auth_data); fatal (infd, "can't execute login", 1); } /* Parent */ true = 1; IF_NOT_ENCRYPT (ioctl (infd, FIONBIO, &true)); ioctl (master, FIONBIO, &true); ioctl (master, TIOCPKT, &true); netf = infd; /* Needed for cleanup() */ signal (SIGCHLD, cleanup); protocol (infd, master, &auth_data); signal (SIGCHLD, SIG_IGN); cleanup (0);#ifdef SHISHI if (kerberos) { int i; shishi_done (auth_data.h);#ifdef ENCRYPTION if (encrypt_io) { shishi_key_done (auth_data.enckey); for (i = 0; i < 2; i++) { shishi_crypto_close (auth_data.ivtab[i]->ctx); free (auth_data.ivtab[i]->iv); } }#endif }#endif return 0;}intdo_rlogin (int infd, struct auth_data *ap){ struct passwd *pwd; int rc; getstr (infd, &ap->rusername, NULL); getstr (infd, &ap->lusername, NULL); getstr (infd, &ap->term, "TERM="); pwd = getpwnam (ap->lusername); if (pwd == NULL) { syslog (LOG_ERR, "no passwd entry for %s", ap->lusername); fatal (infd, "Permission denied", 0); } if (!allow_root && pwd->pw_uid == 0) { syslog (LOG_ERR, "root logins not permitted"); fatal (infd, "Permission denied", 0); } rc = iruserok (ap->from.sin_addr.s_addr, 0, ap->rusername, ap->lusername); if (rc) syslog (LOG_ERR, "iruserok failed: rusername=%s, lusername=%s", ap->rusername, ap->lusername); return rc;}#if defined(KERBEROS) || defined(SHISHI)intdo_krb_login (int infd, struct auth_data *ap, const char **err_msg){ int rc; err_msg = NULL;#if defined(KRB5) if (kerberos == AUTH_KERBEROS_5) rc = do_krb5_login (infd, ap, err_msg); else#elif defined(SHISHI) if (kerberos == AUTH_KERBEROS_SHISHI) rc = do_shishi_login (infd, ap, err_msg); else#else rc = do_krb4_login (infd, ap, err_msg);#endif if (rc && !err_msg) *err_msg = kerberos_error_string (rc); return rc;}#ifdef KRB4intdo_krb4_login (int infd, struct auth_data *ap, const char **err_msg){ int rc; char instance[INST_SZ], version[VERSION_SZ]; long authopts = 0L; /* !mutual */ struct sockaddr_in faddr; u_char auth_buf[sizeof (AUTH_DAT)]; u_char tick_buf[sizeof (KTEXT_ST)]; Key_schedule schedule; AUTH_DAT *kdata; KTEXT ticket; struct passwd *pwd; kdata = (AUTH_DAT *) auth_buf; ticket = (KTEXT) tick_buf; instance[0] = '*'; instance[1] = '\0';#ifdef ENCRYPTION if (encrypt_io) { rc = sizeof faddr; if (getsockname (0, (struct sockaddr *) &faddr, &rc)) { *err_msg = "getsockname failed"; syslog (LOG_ERR, "getsockname failed: %m"); return 1; } authopts = KOPT_DO_MUTUAL; rc = krb_recvauth (authopts, 0, ticket, "rcmd", instance, &ap->from, &faddr, kdata, "", schedule, version); des_set_key (kdata->session, schedule); } else#endif rc = krb_recvauth (authopts, 0, ticket, "rcmd", instance, &ap->from, NULL, kdata, "", NULL, version); if (rc != KSUCCESS) return 1; getstr (infd, &ap->lusername, NULL); /* get the "cmd" in the rcmd protocol */ getstr (infd, &ap->term, "TERM="); pwd = getpwnam (ap->lusername); if (pwd == NULL) { *err_msg = "getpwnam failed"; syslog (LOG_ERR, "getpwnam failed: %m"); return 1; } /* returns nonzero for no access */ if (kuserok (kdata, ap->lusername) != 0) return 1; if (pwd->pw_uid == 0) syslog (LOG_INFO | LOG_AUTH, "ROOT Kerberos login from %s.%s@%s on %s\n", kdata->pname, kdata->pinst, kdata->prealm, ap->hostname); else syslog (LOG_INFO | LOG_AUTH, "%s Kerberos login from %s.%s@%s on %s\n", pwd->pw_name, kdata->pname, kdata->pinst, kdata->prealm, ap->hostname); return 0;}#endif#ifdef KRB5intdo_krb5_login (int infd, struct auth_data *ap, const char **err_msg){ krb5_auth_context auth_ctx = NULL; krb5_error_code status; krb5_data inbuf; krb5_data version; krb5_authenticator *authenticator; krb5_rcache rcache; krb5_keyblock *key; krb5_ticket *ticket; struct sockaddr_in laddr; int len; struct passwd *pwd; char *name; if (status = krb5_init_context (&ap->context)) { syslog (LOG_ERR, "Error initializing krb5: %s", error_message (status)); return status; } if ((status = krb5_auth_con_init (ap->context, &auth_ctx)) || (status = krb5_auth_con_genaddrs (ap->context, auth_ctx, infd, KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) || (status = krb5_auth_con_getrcache (ap->context, auth_ctx, &rcache))) return status; if (!rcache) { krb5_principal server; status = krb5_sname_to_principal (ap->context, 0, 0, KRB5_NT_SRV_HST, &server); if (status) return status; status = krb5_get_server_rcache (ap->context, krb5_princ_component (ap->context, server, 0), &rcache); krb5_free_principal (ap->context, server); if (status) return status; status = krb5_auth_con_setrcache (ap->context, auth_ctx, rcache); if (status) return status; } len = sizeof (laddr); if (getsockname (infd, (struct sockaddr *) &laddr, &len)) return errno; status = krb5_recvauth (ap->context, &auth_ctx, &infd, NULL, 0, 0, ap->keytab, &ticket); if (status) return status; if ((status = krb5_auth_con_getauthenticator (ap->context, auth_ctx, &authenticator))) return status; getstr (infd, &ap->lusername, NULL); getstr (infd, &ap->term, "TERM="); pwd = getpwnam (ap->lusername); if (pwd == NULL) { *err_msg = "getpwnam failed"; syslog (LOG_ERR, "getpwnam failed: %m"); return 1; } getstr (infd, &ap->rusername, NULL); if ((status = krb5_copy_principal (ap->context, ticket->enc_part2->client, &ap->client))) return status; /*OK:: */ if (ap->client && !krb5_kuserok (ap->context, ap->client, ap->lusername)) return 1; krb5_unparse_name (ap->context, ap->client, &name); syslog (LOG_INFO | LOG_AUTH, "%sKerberos V login from %s on %s\n", (pwd->pw_uid == 0) ? "ROOT " : "", name, ap->hostname); free (name); return 0;}#endif#ifdef SHISHIintdo_shishi_login (int infd, struct auth_data *ad, const char **err_msg){ int rc; int error = 0; int keylen, keytype; struct passwd *pwd = NULL; int cksumtype, cksumlen = 30; char *cksum; char *compcksum; size_t compcksumlen; char cksumdata[100]; struct sockaddr_in sock; size_t socklen = sizeof (struct sockaddr_in);#ifdef ENCRYPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -