简单的telnet(带详解)

本文介绍了一个使用C语言编写的简单Telnet服务器,无需用户名和密码即可直接登录系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单的telnet(带详解)

[c-sharp]  view plain copy
  1. #include <stdarg.h>  
  2. #include <errno.h>  
  3. #include <stdio.h>  
  4. #include <fcntl.h>  
  5. #include <unistd.h>  
  6. #include <string.h>  
  7. #include <time.h>  
  8. #include <sys/types.h>  
  9. #include <sys/stat.h>  
  10. #include <dirent.h>  
  11. #include <errno.h>  
  12. #include <netinet/in.h>  
  13. #include <sys/socket.h>  
  14. #include <resolv.h>  
  15. #include <arpa/inet.h>  
  16. #include <stdlib.h>  
  17. #include <signal.h>  
  18. #include <getopt.h>  
  19. #define DEFAULTIP "127.0.0.1" //默认ip  
  20. #define DEFAULTPORT "23" //默认端口port  
  21. #define DEFAULTBACK "10" //默认监听数  
  22. #define DEFAULTDIR "/tmp" //默认登录路径  
  23. #define DEFAULTLOG "/tmp/telnet-server.log"  //默认日志文件  
  24. void prterrmsg(char *msg);  
  25. #define prterrmsg(msg)        { perror(msg); abort(); }  
  26. void wrterrmsg(char *msg);  
  27. #define wrterrmsg(msg)        { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }  
  28. void prtinfomsg(char *msg);  
  29. #define prtinfomsg(msg)        { fputs(msg, stdout);  }  
  30. void wrtinfomsg(char *msg);  
  31. #define wrtinfomsg(msg)        {  fputs(msg, logfp); fflush(logfp);}  
  32. #define MAXBUF        1024  
  33. char buffer[MAXBUF + 1];  
  34. char *host = 0;  
  35. char *port = 0;  
  36. char *back = 0;  
  37. char *dirroot = 0;  
  38. char *logdir = 0;  
  39. unsigned char daemon_y_n = 0;  
  40. FILE *logfp;  
  41. #define MAXPATH        150  
  42. /*------------------------------------------------------ 
  43.  *--- AllocateMemory - 分配空间并把d所指的内容复制 
  44.  *------------------------------------------------------ 
  45.  */  
  46. void AllocateMemory(char **s, int l, char *d)  
  47. {  
  48.     *s = malloc(l + 1);  
  49.     bzero(*s, l + 1);  
  50.     memcpy(*s, d, l);  
  51. }  
  52. /************ 关于本文档************************************************************* 
  53. *filename: telnet-server.c 
  54. *purpose: 这是在Linux下用C语言写的telnet服务器,没有用户名和密码,直接以开启服务者的身份登录系统 
  55. *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) 
  56. Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言 
  57. *date time:2007-01-27 17:02 
  58. *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途 
  59. * 但请遵循GPL 
  60. *Thanks to: Google.com 
  61. *Hope: 希望越来越多的人贡献自己的力量,为科学技术发展出力 
  62. * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献! 
  63. **********************************************************************************/  
  64. /*------------------------------------------------------ 
  65.  *--- getoption - 分析取出程序的参数 
  66.  *------------------------------------------------------ 
  67.  */  
  68. void getoption(int argc, char **argv)  
  69. {  
  70.     int c, len;  
  71.     char *p = 0;  
  72.     opterr = 0;  
  73.     while (1) {  
  74.         int option_index = 0;  
  75.         static struct option long_options[] = {  
  76.             {"host", 1, 0, 0},  
  77.             {"port", 1, 0, 0},  
  78.             {"back", 1, 0, 0},  
  79.             {"dir", 1, 0, 0},  
  80.             {"log", 1, 0, 0},  
  81.             {"daemon", 0, 0, 0},  
  82.             {0, 0, 0, 0}  
  83.         };  
  84.         /* 本程序支持如一些参数: 
  85.          * --host IP地址 或者 -H IP地址 
  86.          * --port 端口 或者 -P 端口 
  87.          * --back 监听数量 或者 -B 监听数量 
  88.          * --dir 服务默认目录 或者 -D 服务默认目录 
  89.          * --log 日志存放路径 或者 -L 日志存放路径 
  90.          * --daemon 使程序进入后台运行模式 
  91.          */  
  92.         c = getopt_long(argc, argv, "H:P:B:D:L",  
  93.                         long_options, &option_index);  
  94.         if (c == -1 || c == '?')  
  95.             break;  
  96.         if(optarg)        len = strlen(optarg);  
  97.         else        len = 0;  
  98.         if ((!c && !(strcasecmp(long_options[option_index].name, "host")))  
  99.             || c == 'H')  
  100.             p = host = malloc(len + 1);  
  101.         else if ((!c  
  102.                   &&  
  103.                   !(strcasecmp(long_options[option_index].name, "port")))  
  104.                  || c == 'P')  
  105.             p = port = malloc(len + 1);  
  106.         else if ((!c  
  107.                   &&  
  108.                   !(strcasecmp(long_options[option_index].name, "back")))  
  109.                  || c == 'B')  
  110.             p = back = malloc(len + 1);  
  111.         else if ((!c  
  112.                   && !(strcasecmp(long_options[option_index].name, "dir")))  
  113.                  || c == 'D')  
  114.             p = dirroot = malloc(len + 1);  
  115.         else if ((!c  
  116.                   && !(strcasecmp(long_options[option_index].name, "log")))  
  117.                  || c == 'L')  
  118.             p = logdir = malloc(len + 1);  
  119.         else if ((!c  
  120.                   &&  
  121.                   !(strcasecmp  
  122.                     (long_options[option_index].name, "daemon")))) {  
  123.             daemon_y_n = 1;  
  124.             continue;  
  125.         }  
  126.         else  
  127.             break;  
  128.         bzero(p, len + 1);  
  129.         memcpy(p, optarg, len);  
  130.     }  
  131. }  
  132. int main(int argc, char **argv)  
  133. {  
  134.     struct sockaddr_in addr;  
  135.     int sock_fd, addrlen;  
  136.     /* 获得程序工作的参数,如 IP 、端口、监听数、网页根目录、目录存放位置等 */  
  137.     //getoption(argc, argv);  
  138.     if (!host) {  
  139.         addrlen = strlen(DEFAULTIP);  
  140.         AllocateMemory(&host, addrlen, DEFAULTIP);  
  141.     }  
  142.     if (!port) {  
  143.         addrlen = strlen(DEFAULTPORT);  
  144.         AllocateMemory(&port, addrlen, DEFAULTPORT);  
  145.     }  
  146.     if (!back) {  
  147.         addrlen = strlen(DEFAULTBACK);  
  148.         AllocateMemory(&back, addrlen, DEFAULTBACK);  
  149.     }  
  150.     if (!dirroot) {  
  151.         addrlen = strlen(DEFAULTDIR);  
  152.         AllocateMemory(&dirroot, addrlen, DEFAULTDIR);  
  153.     }  
  154.     if (!logdir) {  
  155.         addrlen = strlen(DEFAULTLOG);  
  156.         AllocateMemory(&logdir, addrlen, DEFAULTLOG);  
  157.     }  
  158.     printf  
  159.         ("host=%s port=%s back=%s dirroot=%s logdir=%s It is %s daemon mode(PID:%d)/n",  
  160.          host, port, back, dirroot, logdir, daemon_y_n?"":"not", getpid());  
  161.     /* fork() 两次处于后台工作模式下 */  
  162.     if (daemon_y_n) {  
  163.         if (fork())  
  164.             exit(0);  
  165.         if (fork())  
  166.             exit(0);  
  167.         close(0), close(1), close(2);  
  168.         logfp = fopen(logdir, "a+");  
  169.         if (!logfp)  
  170.             exit(0);  
  171.     }  
  172.     /* 处理子进程退出以免产生僵尸进程 */  
  173.     signal(SIGCHLD, SIG_IGN);  
  174.     /* 创建 socket */  
  175.     if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {  
  176.         if (!daemon_y_n) {  
  177.             prterrmsg("socket()");  
  178.         } else {  
  179.             wrterrmsg("socket()");  
  180.         }  
  181.     }  
  182.     /* 设置端口快速重用 */  
  183.     addrlen = 1;  
  184.     setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen,  
  185.                sizeof(addrlen));  
  186.     addr.sin_family = AF_INET;  
  187.     addr.sin_port = htons(atoi(port));  
  188.     addr.sin_addr.s_addr = inet_addr(host);  
  189.     addrlen = sizeof(struct sockaddr_in);  
  190.     /* 绑定地址、端口等信息 */  
  191.     if (bind(sock_fd, (struct sockaddr *) &addr, addrlen) < 0) {  
  192.         if (!daemon_y_n) {  
  193.             prterrmsg("bind()");  
  194.         } else {  
  195.             wrterrmsg("bind()");  
  196.         }  
  197.     }  
  198.     /* 开启临听 */  
  199.     if (listen(sock_fd, atoi(back)) < 0) {  
  200.         if (!daemon_y_n) {  
  201.             prterrmsg("listen()");  
  202.         } else {  
  203.             wrterrmsg("listen()");  
  204.         }  
  205.     }  
  206.     while (1) {  
  207.         int new_fd;  
  208.         int num;  
  209.         addrlen = sizeof(struct sockaddr_in);  
  210.         /* 接受新连接请求 */  
  211.         new_fd = accept(sock_fd, (struct sockaddr *) &addr, &addrlen);  
  212.         if (new_fd < 0) {  
  213.             if (!daemon_y_n) {  
  214.                 prterrmsg("accept()");  
  215.             } else {  
  216.                 wrterrmsg("accept()");  
  217.             }  
  218.             break;  
  219.         }  
  220.         bzero(buffer, MAXBUF + 1);  
  221.         sprintf(buffer, "connect from : %s:%d/n",  
  222.                 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));  
  223.         if (!daemon_y_n) {  
  224.             prtinfomsg(buffer);  
  225.         } else {  
  226.             wrtinfomsg(buffer);  
  227.         }  
  228.         /* 产生一个子进程去处理请求,当前进程继续等待新的连接到来 */  
  229.         if (!fork()) {  
  230.             /* dup2()把socket连接作为标准输入0、输出1、出错句柄2来用 */  
  231.             dup2(new_fd, 0);  
  232.             dup2(new_fd, 1);  
  233.             dup2(new_fd, 2);  
  234.               
  235.               
  236.             printf( "hello/n/n" );  
  237.             /* while(1)//lxb所测试用的菜单 
  238.             { 
  239.                 printf("1、打印111111 "); 
  240.                 printf("2、打印222222 "); 
  241.                 printf("3、打印333333 /n/ninput:/n"); 
  242.                 scanf("%d",&num); 
  243.                  
  244.                 switch(num) 
  245.                 { 
  246.                     case 1: printf("11111/n");break; 
  247.                     case 2: printf("22222/n");break; 
  248.                     case 3: printf("33333/n");break; 
  249.                 } 
  250.             } */  
  251.               
  252.                   
  253.             /* 切换到指定目录工作 */  
  254.             chdir(dirroot);  
  255.             /* 交互式执行shell */  
  256.             execl("/bin/bash""-l""--login""-i""-r""-s", (char *)NULL);  
  257.         }  
  258.         close(new_fd);  
  259.     }  
  260.     close(sock_fd);  
  261.     return 0;  
  262. }  

用下列命令编译程序:
gcc -Wall telnet-server -o telnetd

启动telnet服务:
./telnetd --daemon #以root用户身份在23端口(即telnet默认端口服务)

./telnetd -P 7838 #以非root用户身份

然后开启一个新终端,telnet连接自己的服务器试试,如:
telnet 127.0.0.1

telnet 127.0.0.1 7838

不需要输入用户名和密码,直接以启动telnet服务的用户的身份登录系统了。
输入系统命令体验一 下吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值