首页 电脑 电脑学堂 查看内容

SCO UNIX一个控制登陆的程序

2005-8-4 00:36 467 0

摘要: /* mytcpwrap.c   功能:类似著名的 tcpwrap         根据配置文件,允许某些地址的用户进行登陆连接   &nb...
关键词: nbsp 端口 return char ips sin sizeof include 时间 int

/* mytcpwrap.c   功能:类似著名的 tcpwrap         根据配置文件,允许某些地址的用户进行登陆连接         除可记录登陆时间外,还可以记录退出时间         本程序应由超级服务器inetd启动   使用:替换/etc/inetd.conf 中要进行控制的端口         以telnet、ftp端口控制为例:         /etc/inetd.conf 原内容:         ftp    stream  tcp nowait  root   /etc/ftpd      ftpd         telnet stream  tcp nowait  NOLUID /etc/telnetd   telnetd         改为:         ftp    stream  tcp nowait  root   /etc/mytcpwrap /etc/ftpd         telnet stream  tcp nowait  NOLUID /etc/mytcpwrap /etc/telnetd   注意:改完后记得通知一下inetd进程 */ #include "stdio.h" #include "errno.h" #include "time.h" #include "signal.h" #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include "sys/stat.h" #include "sys/times.h" #define INET_ADDRESTRLEN 18 #define MAXSOCKADDR      64 /* 地址配置文件   格式 port ips        '#' 打头表示本行为注释        'S' 打头表示网络日志记录地,格式为 S port ips            缺省为 5678 1.1.1.1   接受通配符 *   其中 port 记录本地端口,可以使用通配符 * 表示任意端口        ips  允许访问的远程IP地址,形如 nnn.nnn.nnn.nnn             可以使用通配符 * 表示任意地址   例:  21 1.1.1.1 表示1.1.1.1的机器可以访问本机21(ftp)端口        *  2.2.2.2 表示2.2.2.2的机器可以访问本机任意端口        23 3.3.3.* 表示3.3.3.*网段的机器可以访问本机23(telnet)端口 */ #define INIFILE      "/etc/mytcpwrap.conf" #define LOGFILE      "/usr/adm/mytcpwrap.log" short R_PORT=5678; char  R_ADDR[16]="1.1.1.1"; /* 简单字符串比较函数 */ int  cj_Compare(char *so, char *sd) {   char *to,*td;   int  done,cjOk=0,i,k;   if (*sd==0) return 0;   for (done=0,to=so,td=sd;!done; ) {      if (*td=='?') {         td++; to++;      }      else if (*td=='*') {         if (cj_Compare(to,(td+1))==0) return 0;         else to++;      }      else {         cjOk = done = *to - *td;         td++; to++;      }      if (*to==0) for ( ;(*td=='?')||(*td=='*');td++);      if ((*to==0)&&(*td==0)) break;      else if (*to==0) done = cjOk = -1;      else if (*td==0) done = cjOk = -1;   }   return cjOk; } int  is_denied(char *s, int lport) {   int  k, ct;   char buf[128], ips[32], pts[8];   FILE *fp;   /* 读配置文件 */   fp = fopen(INIFILE, "rt");   if (fp){      memset(buf, 0, sizeof(buf));      fgets(buf, sizeof(buf)-1, fp);      while (!feof(fp)){         memset(pts, 0, sizeof(pts));         memset(ips, 0, sizeof(ips));         sscanf(buf, "%5s%15s", pts, ips);         if (pts[0]!='#'){            if (pts[0]!='S' && pts[0]!='s'){               /* 去除末尾单独的'.' */               while (ips[strlen(ips)-1]=='.') ips[strlen(ips)-1]=0;               for (ct=k=0;k<strlen(ips);k++)                  if (ips[k]=='.') ct++;               /* 补齐 nnn.nnn.nnn.nnn 的格式 */               while (ct<3){                  strcat(ips, ".*"); ct++;               }               /* 端口号是否一致或是任意端口 */               if (pts[0]=='*' || atoi(pts)==lport){                  /* 比较IP地址是否满足匹配规则 */                  if (cj_Compare(s, ips)==0){                     fclose(fp);                     /* 返回成功--接受登录 */                     return 0;                  }               }            }            else{               /* 读网络日志服务器地址、端口 */               memset(pts, 0, sizeof(pts));               memset(ips, 0, sizeof(ips));               sscanf(buf, "%*s%5s%15s", pts, R_ADDR);               R_PORT = atoi(pts);            }         }         memset(buf, 0, sizeof(buf));         fgets(buf, sizeof(buf)-1, fp);      }      fclose(fp);   }   /* 未找到匹配记录,拒绝登录 */   return 1; } char *inet_ntop(int f, void *a, char *s, int l) {   u_char *p=(u_char *)a;   struct in_addr inv;   char tt[INET_ADDRESTRLEN];   if (f==AF_INET){      snprintf(tt, sizeof(tt), "%d.%d.%d.%d",p[0], p[1], p[2], p[3]);      if (strlen(tt)>l){         errno = ENOSPC;         return NULL;      }      strcpy(s, tt);      return tt;   }   errno = EAFNOSUPPORT;   return NULL; } sock_ntop(struct sockaddr * sa, int len, char *s) {   char str[128];   int  pt=-1;   struct sockaddr_in *sin=(struct sockaddr_in *)sa;   s[0] = 0;   switch(sa->sa_family){   case AF_INET:if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str))==NULL)                   return NULL;                pt = ntohs(sin->sin_port);                strcpy(s, str);                break;   };   return pt; } get_time(int t[6]) {   struct tm *tm;   time_t n;   n = time(NULL);   tm = localtime(&n);   t[0] = tm->tm_year + 1900;   t[1] = tm->tm_mon+1;   t[2] = tm->tm_mday;   t[3] = tm->tm_hour;   t[4] = tm->tm_min;   t[5] = tm->tm_sec; } long rowid=0; /* 将登录信息记录到网络上日志服务器上   通过两次提交记录完整的登陆、退出时间     第一次记录登录时间   发送格式: NETLOG|本地服务端口|客户地址|端口|成功标志|   服务端返回一个该记录的rowid值   第二次记录离开时间   发送格式: NETUPD|原记录的rowid */ int  net_logit(int lport, char *ips, int rport, int succ) {   int    i,s;   struct sockaddr_in sin;   struct hostent *hp;   char buf[128], ss[64];   if (R_PORT==0 || strlen(R_ADDR)==0) return -1;   bzero((char *)&sin,sizeof(sin));   sin.sin_family = AF_INET;   /* 取日志服务器地址 */   hp = gethostbyname(R_ADDR);   if (hp!=NULL)      bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);   else      inet_aton(R_ADDR, &sin.sin_addr);   sin.sin_port = htons(R_PORT);   s = socket(AF_INET, SOCK_STREAM, 0);   if (s<0) return 1;   /* 连接日志服务器 */   if ((i=connect(s, (struct sockaddr *)&sin,sizeof(sin)))<0){      close(s);      return 2;   }   /* 发送日志信息 格式: NETLOG|本地服务端口|客户地址|端口|成功标志| */   /* 第一次记录登录时间 */   if (rowid==0)      sprintf(ss, "NETLOG|%d|%s|%d|%d|", lport, ips, rport, succ);   else   /* 第二次记录离开时间,发送信息格式: NETUPD|原记录的rowid */      sprintf(ss, "NETUPD|%d|", rowid);   sprintf(buf, "%04d%s", strlen(ss), ss);   write(s, buf, strlen(buf));   memset(ss, 0, sizeof(ss));   if (rowid==0){      /* 取该记录的rowid */      read(s, ss, sizeof(ss)-1);      rowid = atol(ss);   }   /* 关闭连接 */   shutdown(s, 2);   close(s);   return 0; } void mysig(int sig) {   return ; } main(int argc, char *argv[], char *envp[]) {   int  srq[6], i, ct, k, rport, lport;   unsigned int len;   char buf[128], ips[32];   FILE *fp;   union{      struct sockaddr sa;      char   data[MAXSOCKADDR];   }from;   /* 取本地端口 */   len = sizeof(from);   k = getsockname(1, (struct sockaddr *)&from.data, &len);   lport = sock_ntop(&from.sa, len, ips);   /* 取远程端口、地址 */   len = sizeof(from);   k = getpeername(1, (struct sockaddr *)&from.data, &len);   rport = sock_ntop(&from.sa, len, ips);   get_time(srq);   sprintf(buf, "端口 %d, 来自 %15s:%d, 时间 %04d/%02d/%02d %02d:%02d:%02d ",                lport, ips, rport, srq[0], srq[1], srq[2],                srq[3], srq[4], srq[5]);   fp = fopen(LOGFILE, "at");   if (fp!=NULL)      fprintf(fp, "%s", buf);   k = is_denied(ips, lport);   /* 记录登录时间 */   net_logit(lport, ips, rport, k);   if (k){      fprintf(stderr,"对不起,您没有在此主机登录的权限!\007\r\n");      if (fp!=NULL){         fprintf(fp, "...拒绝[%d]!\n", rowid);         fclose(fp);      }      exit(1);   }   if (fp){      fprintf(fp, "...接受[%s][%d]!\n", argv[0], rowid);      fclose(fp);   }   sigset(SIGCLD, mysig);   /* 子进程启动相应程序,父进程等待 */   if (fork()==0)      execve(argv[0], argv, envp);   else pause();   /* 记录退出登录的时间 */   net_logit(lport, ips, rport, k);   return 0; }
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部