static void crypt_setdefault(void) { char *def; size_t i; if (crypt_type != -1) return; def = auth_getval("crypt_default"); if (def == NULL) { crypt_type = 0; return; } for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) { if (strcmp(def, crypt_types[i].name) == 0) { crypt_type = (int)i; return; } } crypt_type = 0; }
int main(int argc, char *argv[]) { struct passwd *pw; struct servent *sp; struct sgttyb ttyb; long omask; int argoff, ch, dflag, Dflag, one, uid; char *host, *localname, *p, *user, term[1024]; #ifdef KERBEROS char *k; #endif struct sockaddr_storage ss; int sslen; argoff = dflag = Dflag = 0; one = 1; host = localname = user = NULL; if ((p = strrchr(argv[0], '/'))) ++p; else p = argv[0]; if (strcmp(p, "rlogin")) host = p; /* handle "rlogin host flags" */ if (!host && argc > 2 && argv[1][0] != '-') { host = argv[1]; argoff = 1; } #ifdef KERBEROS #define OPTIONS "468DEKLde:i:k:l:x" #else #define OPTIONS "468DEKLde:i:l:" #endif while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1) switch(ch) { case '4': family = PF_INET; break; case '6': family = PF_INET6; break; case '8': eight = 1; break; case 'D': Dflag = 1; break; case 'E': noescape = 1; break; case 'K': #ifdef KERBEROS use_kerberos = 0; #endif break; case 'L': litout = 1; break; case 'd': dflag = 1; break; case 'e': noescape = 0; escapechar = getescape(optarg); break; case 'i': if (getuid() != 0) errx(1, "-i user: permission denied"); localname = optarg; break; #ifdef KERBEROS case 'k': dest_realm = dst_realm_buf; (void)strncpy(dest_realm, optarg, REALM_SZ); break; #endif case 'l': user = optarg; break; #ifdef CRYPT #ifdef KERBEROS case 'x': doencrypt = 1; break; #endif #endif case '?': default: usage(); } optind += argoff; /* if haven't gotten a host yet, do so */ if (!host && !(host = argv[optind++])) usage(); if (argv[optind]) usage(); if (!(pw = getpwuid(uid = getuid()))) errx(1, "unknown user id"); if (!user) user = pw->pw_name; if (!localname) localname = pw->pw_name; sp = NULL; #ifdef KERBEROS k = auth_getval("auth_list"); if (k && !strstr(k, "kerberos")) use_kerberos = 0; if (use_kerberos) { sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp"); if (sp == NULL) { use_kerberos = 0; warn("can't get entry for %s/tcp service", doencrypt ? "eklogin" : "klogin"); } } #endif if (sp == NULL) sp = getservbyname("login", "tcp"); if (sp == NULL) errx(1, "login/tcp: unknown service"); #define MAX_TERM_LENGTH (sizeof(term) - 1 - MAX_SPEED_LENGTH - 1) (void)strncpy(term, (p = getenv("TERM")) ? p : "network", MAX_TERM_LENGTH); term[MAX_TERM_LENGTH] = '\0'; if (ioctl(0, TIOCGETP, &ttyb) == 0) { (void)strcat(term, "/"); (void)strcat(term, speeds[(int)ttyb.sg_ospeed]); } (void)get_window_size(0, &winsize); (void)signal(SIGPIPE, lostpeer); /* will use SIGUSR1 for window size hack, so hold it off */ omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); /* * We set SIGURG and SIGUSR1 below so that an * incoming signal will be held pending rather than being * discarded. Note that these routines will be ready to get * a signal by the time that they are unblocked below. */ (void)signal(SIGURG, copytochild); (void)signal(SIGUSR1, writeroob); #ifdef KERBEROS if (use_kerberos) { setuid(getuid()); rem = KSUCCESS; errno = 0; if (dest_realm == NULL) dest_realm = krb_realmofhost(host); #ifdef CRYPT if (doencrypt) { rem = krcmd_mutual(&host, sp->s_port, user, term, 0, dest_realm, &cred, schedule); des_set_key(&cred.session, schedule); } else #endif /* CRYPT */ rem = krcmd(&host, sp->s_port, user, term, 0, dest_realm); if (rem < 0) { int i; char **newargv; sp = getservbyname("login", "tcp"); if (sp == NULL) errx(1, "unknown service login/tcp"); if (errno == ECONNREFUSED) warn("remote host doesn't support Kerberos"); if (errno == ENOENT) warn("can't provide Kerberos auth data"); newargv = malloc((argc + 2) * sizeof(*newargv)); if (newargv == NULL) err(1, "malloc"); newargv[0] = argv[0]; newargv[1] = "-K"; for(i = 1; i < argc; ++i) newargv[i + 1] = argv[i]; newargv[argc + 1] = NULL; execv(_PATH_RLOGIN, newargv); } } else { #ifdef CRYPT if (doencrypt) errx(1, "the -x flag requires Kerberos authentication"); #endif /* CRYPT */ rem = rcmd_af(&host, sp->s_port, localname, user, term, 0, family); } #else rem = rcmd_af(&host, sp->s_port, localname, user, term, 0, family); #endif /* KERBEROS */ if (rem < 0) exit(1); if (dflag && setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) warn("setsockopt"); if (Dflag && setsockopt(rem, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) warn("setsockopt NODELAY (ignored)"); sslen = sizeof(ss); one = IPTOS_LOWDELAY; if (getsockname(rem, (struct sockaddr *)&ss, &sslen) == 0 && ss.ss_family == AF_INET) { if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0) warn("setsockopt TOS (ignored)"); } else if (ss.ss_family == AF_INET) warn("setsockopt getsockname failed"); (void)setuid(uid); doit(omask); /*NOTREACHED*/ }