免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3668 | 回复: 10
打印 上一主题 下一主题

[SCO UNIX] 自己的一个控制登陆的程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-07-29 16:45 |只看该作者 |倒序浏览
看到不少关于如何控制网络登陆的好帖子
这里贴个自己写的在本人所在单位使用的东东
还请高人指正

  1. /* mytcpwrap.c
  2.    功能:类似著名的 tcpwrap
  3.          根据配置文件,允许某些地址的用户进行登陆连接
  4.          除可记录登陆时间外,还可以记录退出时间
  5.          本程序应由超级服务器inetd启动
  6.    使用:替换/etc/inetd.conf 中要进行控制的端口
  7.          以telnet、ftp端口控制为例:
  8.          /etc/inetd.conf 原内容:

  9.          ftp    stream  tcp nowait  root   /etc/ftpd      ftpd
  10.          telnet stream  tcp nowait  NOLUID /etc/telnetd   telnetd

  11.          改为:

  12.          ftp    stream  tcp nowait  root   /etc/mytcpwrap /etc/ftpd
  13.          telnet stream  tcp nowait  NOLUID /etc/mytcpwrap /etc/telnetd

  14.    注意:改完后记得通知一下inetd进程
  15. */
  16. #include "stdio.h"
  17. #include "errno.h"
  18. #include "time.h"
  19. #include "signal.h"

  20. #include <sys/types.h>;
  21. #include <sys/socket.h>;
  22. #include <netinet/in.h>;
  23. #include <netdb.h>;
  24. #include "sys/stat.h"
  25. #include "sys/times.h"

  26. #define INET_ADDRESTRLEN 18
  27. #define MAXSOCKADDR      64

  28. /* 地址配置文件
  29.    格式 port ips
  30.         '#' 打头表示本行为注释
  31.         'S' 打头表示网络日志记录地,格式为 S port ips
  32.             缺省为 5678 1.1.1.1
  33.    接受通配符 *
  34.    其中 port 记录本地端口,可以使用通配符 * 表示任意端口
  35.         ips  允许访问的远程IP地址,形如 nnn.nnn.nnn.nnn
  36.              可以使用通配符 * 表示任意地址
  37.    例:  21 1.1.1.1 表示1.1.1.1的机器可以访问本机21(ftp)端口
  38.         *  2.2.2.2 表示2.2.2.2的机器可以访问本机任意端口
  39.         23 3.3.3.* 表示3.3.3.*网段的机器可以访问本机23(telnet)端口
  40. */
  41. #define INIFILE                "/etc/mytcpwrap.conf"
  42. #define LOGFILE                "/usr/adm/mytcpwrap.log"

  43. short R_PORT=5678;
  44. char  R_ADDR[16]="1.1.1.1";

  45. /* 简单字符串比较函数 */
  46. int  cj_Compare(char *so, char *sd)
  47. {
  48.    char *to,*td;
  49.    int  done,cjOk=0,i,k;

  50.    if (*sd==0) return 0;
  51.    for (done=0,to=so,td=sd;!done; ) {
  52.       if (*td=='?') {
  53.          td++; to++;
  54.       }
  55.       else if (*td=='*') {
  56.          if (cj_Compare(to,(td+1))==0) return 0;
  57.          else to++;
  58.       }
  59.       else {
  60.          cjOk = done = *to - *td;
  61.          td++; to++;
  62.       }
  63.       if (*to==0) for ( ;(*td=='?')||(*td=='*');td++);
  64.       if ((*to==0)&&(*td==0)) break;
  65.       else if (*to==0) done = cjOk = -1;
  66.       else if (*td==0) done = cjOk = -1;
  67.    }
  68.    return cjOk;
  69. }

  70. int  is_denied(char *s, int lport)
  71. {
  72.    int  k, ct;
  73.    char buf[128], ips[32], pts[8];
  74.    FILE *fp;

  75.    /* 读配置文件 */
  76.    fp = fopen(INIFILE, "rt");
  77.    if (fp){
  78.       memset(buf, 0, sizeof(buf));
  79.       fgets(buf, sizeof(buf)-1, fp);
  80.       while (!feof(fp)){
  81.          memset(pts, 0, sizeof(pts));
  82.          memset(ips, 0, sizeof(ips));
  83.          sscanf(buf, "%5s%15s", pts, ips);
  84.          if (pts[0]!='#'){
  85.             if (pts[0]!='S' && pts[0]!='s'){
  86.                /* 去除末尾单独的'.' */
  87.                while (ips[strlen(ips)-1]=='.') ips[strlen(ips)-1]=0;
  88.                for (ct=k=0;k<strlen(ips);k++)
  89.                   if (ips[k]=='.') ct++;
  90.                /* 补齐 nnn.nnn.nnn.nnn 的格式 */
  91.                while (ct<3){
  92.                   strcat(ips, ".*"); ct++;
  93.                }
  94.                /* 端口号是否一致或是任意端口 */
  95.                if (pts[0]=='*' || atoi(pts)==lport){
  96.                   /* 比较IP地址是否满足匹配规则 */
  97.                   if (cj_Compare(s, ips)==0){
  98.                      fclose(fp);
  99.                      /* 返回成功--接受登录 */
  100.                      return 0;
  101.                   }
  102.                }
  103.             }
  104.             else{
  105.                /* 读网络日志服务器地址、端口 */
  106.                memset(pts, 0, sizeof(pts));
  107.                memset(ips, 0, sizeof(ips));
  108.                sscanf(buf, "%*s%5s%15s", pts, R_ADDR);
  109.                R_PORT = atoi(pts);
  110.             }
  111.          }
  112.          memset(buf, 0, sizeof(buf));
  113.          fgets(buf, sizeof(buf)-1, fp);
  114.       }
  115.       fclose(fp);
  116.    }
  117.    /* 未找到匹配记录,拒绝登录 */
  118.    return 1;
  119. }

  120. char *inet_ntop(int f, void *a, char *s, int l)
  121. {
  122.    u_char *p=(u_char *)a;
  123.    struct in_addr inv;
  124.    char tt[INET_ADDRESTRLEN];

  125.    if (f==AF_INET){
  126.       snprintf(tt, sizeof(tt), "%d.%d.%d.%d",p[0], p[1], p[2], p[3]);
  127.       if (strlen(tt)>;l){
  128.          errno = ENOSPC;
  129.          return NULL;
  130.       }
  131.       strcpy(s, tt);
  132.       return tt;
  133.    }
  134.    errno = EAFNOSUPPORT;
  135.    return NULL;
  136. }

  137. sock_ntop(struct sockaddr * sa, int len, char *s)
  138. {
  139.    char str[128];
  140.    int  pt=-1;
  141.    struct sockaddr_in *sin=(struct sockaddr_in *)sa;

  142.    s[0] = 0;
  143.    switch(sa->;sa_family){
  144.    case AF_INET:if (inet_ntop(AF_INET, &sin->;sin_addr, str, sizeof(str))==NULL)
  145.                    return NULL;
  146.                 pt = ntohs(sin->;sin_port);
  147.                 strcpy(s, str);
  148.                 break;
  149.    };
  150.    return pt;
  151. }

  152. get_time(int t[6])
  153. {
  154.    struct tm *tm;
  155.    time_t n;

  156.    n = time(NULL);
  157.    tm = localtime(&n);
  158.    t[0] = tm->;tm_year + 1900;
  159.    t[1] = tm->;tm_mon+1;
  160.    t[2] = tm->;tm_mday;
  161.    t[3] = tm->;tm_hour;
  162.    t[4] = tm->;tm_min;
  163.    t[5] = tm->;tm_sec;
  164. }

  165. long rowid=0;
  166. /* 将登录信息记录到网络上日志服务器上
  167.    通过两次提交记录完整的登陆、退出时间
  168.    
  169.    第一次记录登录时间
  170.    发送格式: NETLOG|本地服务端口|客户地址|端口|成功标志|
  171.    服务端返回一个该记录的rowid值
  172.    第二次记录离开时间
  173.    发送格式: NETUPD|原记录的rowid
  174. */
  175. int  net_logit(int lport, char *ips, int rport, int succ)
  176. {
  177.    int    i,s;
  178.    struct sockaddr_in sin;
  179.    struct hostent *hp;
  180.    char buf[128], ss[64];

  181.    if (R_PORT==0 || strlen(R_ADDR)==0) return -1;
  182.    bzero((char *)&sin,sizeof(sin));
  183.    sin.sin_family = AF_INET;
  184.    /* 取日志服务器地址 */
  185.    hp = gethostbyname(R_ADDR);
  186.    if (hp!=NULL)
  187.       bcopy(hp->;h_addr, (char *)&sin.sin_addr, hp->;h_length);
  188.    else
  189.       inet_aton(R_ADDR, &sin.sin_addr);
  190.    sin.sin_port = htons(R_PORT);
  191.    s = socket(AF_INET, SOCK_STREAM, 0);
  192.    if (s<0) return 1;
  193.    /* 连接日志服务器 */
  194.    if ((i=connect(s, (struct sockaddr *)&sin,sizeof(sin)))<0){
  195.       close(s);
  196.       return 2;
  197.    }
  198.    /* 发送日志信息 格式: NETLOG|本地服务端口|客户地址|端口|成功标志| */
  199.    /* 第一次记录登录时间 */
  200.    if (rowid==0)
  201.       sprintf(ss, "NETLOG|%d|%s|%d|%d|", lport, ips, rport, succ);
  202.    else
  203.    /* 第二次记录离开时间,发送信息格式: NETUPD|原记录的rowid */
  204.       sprintf(ss, "NETUPD|%d|", rowid);
  205.    sprintf(buf, "%04d%s", strlen(ss), ss);
  206.    write(s, buf, strlen(buf));
  207.    memset(ss, 0, sizeof(ss));
  208.    if (rowid==0){
  209.       /* 取该记录的rowid */
  210.       read(s, ss, sizeof(ss)-1);
  211.       rowid = atol(ss);
  212.    }
  213.    /* 关闭连接 */
  214.    shutdown(s, 2);
  215.    close(s);
  216.    return 0;
  217. }

  218. void mysig(int sig)
  219. {
  220.    return ;
  221. }

  222. main(int argc, char *argv[], char *envp[])
  223. {
  224.    int  srq[6], i, ct, k, rport, lport;
  225.    unsigned int len;
  226.    char buf[128], ips[32];
  227.    FILE *fp;
  228.    union{
  229.       struct sockaddr sa;
  230.       char   data[MAXSOCKADDR];
  231.    }from;

  232.    /* 取本地端口 */
  233.    len = sizeof(from);
  234.    k = getsockname(1, (struct sockaddr *)&from.data, &len);
  235.    lport = sock_ntop(&from.sa, len, ips);
  236.    /* 取远程端口、地址 */
  237.    len = sizeof(from);
  238.    k = getpeername(1, (struct sockaddr *)&from.data, &len);
  239.    rport = sock_ntop(&from.sa, len, ips);
  240.    get_time(srq);
  241.    sprintf(buf, "端口 %d, 来自 %15s:%d, 时间 %04d/%02d/%02d %02d:%02d:%02d ",
  242.                 lport, ips, rport, srq[0], srq[1], srq[2],
  243.                 srq[3], srq[4], srq[5]);
  244.    fp = fopen(LOGFILE, "at");
  245.    if (fp!=NULL)
  246.       fprintf(fp, "%s", buf);
  247.    k = is_denied(ips, lport);
  248.    /* 记录登录时间 */
  249.    net_logit(lport, ips, rport, k);
  250.    if (k){
  251.       fprintf(stderr,"对不起,您没有在此主机登录的权限!\007\r\n");
  252.       if (fp!=NULL){
  253.          fprintf(fp, "...拒绝[%d]!\n", rowid);
  254.          fclose(fp);
  255.       }
  256.       exit(1);
  257.    }
  258.    if (fp){
  259.       fprintf(fp, "...接受[%s][%d]!\n", argv[0], rowid);
  260.       fclose(fp);
  261.    }
  262.    sigset(SIGCLD, mysig);
  263.    /* 子进程启动相应程序,父进程等待 */
  264.    if (fork()==0)
  265.       execve(argv[0], argv, envp);
  266.    else pause();
  267.    /* 记录退出登录的时间 */
  268.    net_logit(lport, ips, rport, k);
  269.    return 0;
  270. }

复制代码

论坛徽章:
0
2 [报告]
发表于 2005-08-02 00:05 |只看该作者

自己的一个控制登陆的程序

收下

论坛徽章:
0
3 [报告]
发表于 2005-08-09 10:22 |只看该作者

自己的一个控制登陆的程序

我看看 不知道测试情况怎么样?

论坛徽章:
0
4 [报告]
发表于 2005-08-09 11:08 |只看该作者

自己的一个控制登陆的程序

收下先,

论坛徽章:
0
5 [报告]
发表于 2005-08-10 17:13 |只看该作者

自己的一个控制登陆的程序

程序不错,但实现这个功能好像不用这么麻烦,我记得在系统下配个文件就可以了.

论坛徽章:
0
6 [报告]
发表于 2005-08-10 18:09 |只看该作者

自己的一个控制登陆的程序

mark!

论坛徽章:
0
7 [报告]
发表于 2005-08-11 10:55 |只看该作者

自己的一个控制登陆的程序

先收,看看。。。谢谢。

论坛徽章:
0
8 [报告]
发表于 2005-08-11 15:52 |只看该作者

自己的一个控制登陆的程序

使用shell就可以实现的。不过还是说,不错的。

论坛徽章:
0
9 [报告]
发表于 2005-08-12 20:28 |只看该作者

自己的一个控制登陆的程序

不错

论坛徽章:
0
10 [报告]
发表于 2006-01-11 17:10 |只看该作者
仔细阅读。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP