📄 utelnetd.c
字号:
if (chr == '\n') fputc('\r', stdout); fputc(chr, stdout); } fclose(fp); }#endif /* exec shell, with correct argv and env */ execv(loginpath, argv_init); /* NOT REACHED */ perror_msg_and_die("execv"); } ts->shell_pid = pid; return ts;}static voidfree_session(struct tsession *ts){ struct tsession *t = sessions; /* Unlink this telnet session from the session list. */ if(t == ts) sessions = ts->next; else { while(t->next != ts) t = t->next; t->next = ts->next; } free(ts->buf1); free(ts->buf2); kill(ts->shell_pid, SIGKILL); wait4(ts->shell_pid, NULL, 0, NULL); close(ts->ptyfd); close(ts->sockfd); if(ts->ptyfd == maxfd || ts->sockfd == maxfd) maxfd--; if(ts->ptyfd == maxfd || ts->sockfd == maxfd) maxfd--; free(ts);}int main(int argc, char **argv){ struct sockaddr_in sa; int master_fd; fd_set rdfdset, wrfdset; int selret; int on = 1; int portnbr = 23; int c, ii; int daemonize = 0; char *interface_name = NULL; struct ifreq interface;#ifdef USE_SYSLOG char *appname; appname = strrchr (argv [0], '/'); if (!appname) appname = argv [0]; else appname++;#endif /* check if user supplied a port number */ for (;;) { c = getopt( argc, argv, "i:p:l:hd"); if (c == EOF) break; switch (c) { case 'p': portnbr = atoi(optarg); break; case 'i': interface_name = strdup(optarg); break; case 'l': loginpath = strdup(optarg); break; case 'd': daemonize = 1; break; case 'h': default: show_usage(); exit(1); } } if (!loginpath) { loginpath = SHELLPATH; if (access(loginpath, X_OK) < 0) loginpath = "/bin/sh"; } if (access(loginpath, X_OK) < 0) { /* workaround: error_msg_and_die has doesn't understand variable argument lists yet */ fprintf(stderr,"\"%s\"",loginpath); perror_msg_and_die(" is no valid executable!\n"); } printf("telnetd: starting\n"); printf(" port: %i; interface: %s; login program: %s\n", portnbr, (interface_name)?interface_name:"any", loginpath); argv_init[0] = loginpath; sessions = 0; /* Grab a TCP socket. */ master_fd = socket(AF_INET, SOCK_STREAM, 0); if (master_fd < 0) { perror("socket"); return 1; } (void)setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); /* Set it to listen to specified port */ memset((void *)&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(portnbr); /* Set it to listen on the specified interface */ if (interface_name) { strcpy(interface.ifr_name, interface_name); /* use ioctl() here as BSD does not have setsockopt() */ if (ioctl(master_fd, SIOCGIFADDR, &interface) < 0) { printf("Please check the NIC you specified with -i option\n"); perror("ioctl SIOCGFADDR"); return 1; } sa.sin_addr = ((struct sockaddr_in *)(&interface.ifr_addr))->sin_addr; } else sa.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(master_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("bind"); return 1; } if (listen(master_fd, 1) < 0) { perror("listen"); return 1; } if (daemonize) { DEBUG_OUT(" daemonizing\n"); if (daemon(0, 1) < 0) perror_msg_and_die("daemon"); }#ifdef USE_SYSLOG openlog(appname , LOG_NDELAY | LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "%s (port: %i, ifname: %s, login: %s) startup succeeded\n"\ , appname, portnbr, (interface_name)?interface_name:"any", loginpath); closelog();#endif maxfd = master_fd; do { struct tsession *ts; FD_ZERO(&rdfdset); FD_ZERO(&wrfdset); /* select on the master socket, all telnet sockets and their * ptys if there is room in their respective session buffers. */ FD_SET(master_fd, &rdfdset); ts = sessions; while (ts) { /* buf1 is used from socket to pty * buf2 is used from pty to socket */ if (ts->size1 > 0) { FD_SET(ts->ptyfd, &wrfdset); /* can write to pty */ } if (ts->size1 < BUFSIZE) { FD_SET(ts->sockfd, &rdfdset); /* can read from socket */ } if (ts->size2 > 0) { FD_SET(ts->sockfd, &wrfdset); /* can write to socket */ } if (ts->size2 < BUFSIZE) { FD_SET(ts->ptyfd, &rdfdset); /* can read from pty */ } ts = ts->next; } selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0); if (!selret) break; /* First check for and accept new sessions. */ if (FD_ISSET(master_fd, &rdfdset)) { int fd, salen; salen = sizeof(sa); if ((fd = accept(master_fd, (struct sockaddr *)&sa, &salen)) < 0) { continue; } else { /* Create a new session and link it into our active list. */ struct tsession *new_ts;#ifdef USE_SYSLOG openlog(appname , LOG_NDELAY, LOG_DAEMON); syslog(LOG_INFO, "connection from: %s\n", inet_ntoa(sa.sin_addr)); closelog();#endif new_ts = make_new_session(fd); if (new_ts) { new_ts->next = sessions; sessions = new_ts; if (fd > maxfd) maxfd = fd; } else { close(fd); } } } /* Then check for data tunneling. */ ts = sessions; while (ts) { /* For all sessions... */ int maxlen, w, r; struct tsession *next = ts->next; /* in case we free ts. */ if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset)) { int processed, num_totty; char *ptr; /* Write to pty from buffer 1. */ maxlen = MIN(BUFSIZE - ts->wridx1, ts->size1); ptr = remove_iacs(ts->buf1 + ts->wridx1, maxlen, &processed, &num_totty); /* the difference between processed and num_totty is all the iacs we removed from the stream. Adjust buf1 accordingly. */ ts->wridx1 += processed - num_totty; ts->size1 -= processed - num_totty; w = write(ts->ptyfd, ptr, num_totty); if (w < 0) { perror("write"); free_session(ts); ts = next; continue; } ts->wridx1 += w; ts->size1 -= w; if (ts->wridx1 == BUFSIZE) ts->wridx1 = 0; } if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset)) { /* Write to socket from buffer 2. */ maxlen = MIN(BUFSIZE - ts->wridx2, ts->size2); w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen); if (w < 0) { perror("write"); free_session(ts); ts = next; continue; } ts->wridx2 += w; ts->size2 -= w; if (ts->wridx2 == BUFSIZE) ts->wridx2 = 0; } if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset)) { /* Read from socket to buffer 1. */ maxlen = MIN(BUFSIZE - ts->rdidx1, BUFSIZE - ts->size1); r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen); if (!r || (r < 0 && errno != EINTR)) { free_session(ts); ts = next; continue; } if(!*(ts->buf1 + ts->rdidx1 + r - 1)) { r--; if(!r) continue; } ts->rdidx1 += r; ts->size1 += r; if (ts->rdidx1 == BUFSIZE) ts->rdidx1 = 0; } if (ts->size2 < BUFSIZE && FD_ISSET(ts->ptyfd, &rdfdset)) { /* Read from pty to buffer 2. */ maxlen = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2); r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen); if (!r || (r < 0 && errno != EINTR)) { free_session(ts); ts = next; continue; } for (ii=0; ii < r; ii++) if (*(ts->buf2 + ts->rdidx2 + ii) == 3) fprintf(stderr, "found <CTRL>-<C> in data!\n"); ts->rdidx2 += r; ts->size2 += r; if (ts->rdidx2 == BUFSIZE) ts->rdidx2 = 0; } if (ts->size1 == 0) { ts->rdidx1 = 0; ts->wridx1 = 0; } if (ts->size2 == 0) { ts->rdidx2 = 0; ts->wridx2 = 0; } ts = next; } } while (1); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -