sident.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:5k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6. /*
  7.  * $Id: sident.c,v 1.19.2.1 1997/08/25 02:32:43 jduan Exp $
  8.  */
  9. #include "socks5p.h"
  10. #include "threads.h"
  11. #include "daemon.h"
  12. #include "addr.h"
  13. #include "log.h"
  14. #ifdef HAVE_LIBIDENT
  15. #include <ident.h>
  16. #endif
  17. #ifndef IDENTTIMEOUT
  18. #define IDENTTIMEOUT 15
  19. #endif
  20. #ifdef HAVE_LIBIDENT
  21. static inline void filelock(S5IOHandle fd, int on) {
  22. #if defined(HAVE_FLOCK) && !defined(F_SETLKW)
  23.     flock(fd, on?LOCK_EX:LOCK_UN);
  24. #else
  25.     struct flock fl;
  26.     
  27.     fl.l_type   = on?F_WRLCK:F_UNLCK;
  28.     fl.l_whence = SEEK_SET;
  29.     fl.l_start  = 0;
  30.     fl.l_len    = 0;
  31.     fcntl(fd, F_SETLKW, &fl);
  32. #endif
  33. }
  34. static inline S5IOHandle openidtfile(void) {
  35.     int flags = O_RDWR | O_CREAT;
  36.     S5IOHandle fd;
  37.     struct stat sbuf;
  38.     static char *myfile = NULL;
  39.     
  40.     if (!myfile) {
  41.      MUTEX_LOCK(env_mutex);
  42.      myfile = getenv("SOCKS5_IDENTFILE");
  43.      myfile = myfile?strdup(myfile):strdup(SRVIDT_FILE);
  44.     }
  45.     if (lstat(myfile, &sbuf) || (S_ISLNK(sbuf.st_mode) && geteuid() != sbuf.st_uid)) flags |= O_EXCL;
  46.     fd = open(myfile, flags, 0644);
  47.     MUTEX_UNLOCK(env_mutex);
  48.     if (fd == S5InvalidIOHandle) return fd;
  49.     filelock(fd, 1);
  50.     return fd;
  51. }
  52. #endif
  53. int IdentQuery(S5IOHandle fd, char *name) {
  54. #ifndef HAVE_LIBIDENT
  55.     return 0;
  56. #else
  57.     IDENT *idp;
  58.     char *ev;
  59.     int rval;
  60.     IFTHREADED(static MUTEX_T idt_mutex = MUTEX_INITIALIZER;)
  61.     IFTHREADED(MUTEX_SETUP(idt_mutex);)
  62.     MUTEX_LOCK(env_mutex);
  63.     ev = getenv("SOCKS5_NOIDENT");
  64.     MUTEX_UNLOCK(env_mutex);
  65.     
  66.     if (ev) {
  67. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Ident: No Ident lookup (by request)");
  68. *name = '';
  69. return -1;
  70.     } 
  71.     MUTEX_LOCK(idt_mutex);
  72.     if ((idp = ident_lookup(fd, IDENTTIMEOUT)) == NULL) {
  73. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Ident: Ident lookup failed: %m");
  74. *name = '';
  75. rval = -1;
  76.     } else {
  77. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Ident: Ident lookup name was: %s", idp->identifier);
  78. strncpy(name, idp->identifier, MIN(strlen(idp->identifier)+1, S5_USERNAME_SIZE));
  79. if (strlen(idp->identifier)+1 > S5_USERNAME_SIZE) name[S5_USERNAME_SIZE-1] = '';
  80. ident_free(idp);
  81. rval = 0;
  82.     }
  83.     
  84.     MUTEX_UNLOCK(idt_mutex);
  85.     return rval;
  86. #endif
  87. }
  88.     
  89. void InitIdentEntry(char *idtentry) {
  90.     idtentry[0] = '';
  91. }
  92. void RemoveIdentEntry(char *idtentry) {
  93. #ifdef HAVE_LIBIDENT
  94.     char *fbuf = NULL, *offset;
  95.     struct stat sb;
  96.     S5IOHandle fd;
  97.     if (*idtentry == '') return;
  98.     if ((fd = openidtfile()) == S5InvalidIOHandle) return;
  99.     if (fstat(fd, &sb) < 0) goto end;
  100.     if (!(fbuf = (char *)malloc((sb.st_size+1)*sizeof(char)))) goto end;
  101.     if (READFILE(fd, fbuf, sb.st_size) < 0) goto end;
  102.     fbuf[sb.st_size] = '';
  103.     
  104.     if ((offset = strstr(fbuf, idtentry)) == NULL) goto end;
  105.     lseek(fd, offset-fbuf, 0);
  106.     WRITEFILE(fd, offset + strlen(idtentry), (sb.st_size - (offset-fbuf) - strlen(idtentry)));
  107.     /* XXX For now, if you don't have ftruncated, you loose.  BSD & SVR4 */
  108.     /* both do, so there shouldn't be too many losers.                   */
  109.     ftruncate(fd, sb.st_size - strlen(idtentry));
  110.     
  111.   end:
  112.     if (fbuf) free(fbuf);
  113.     if (fd >= 0) close(fd);
  114. #endif
  115. }
  116. void MakeIdentEntry(S5IOHandle in, S5IOHandle out, S5LinkInfo *linkinfo, char *idtentry) {
  117. #ifdef HAVE_LIBIDENT
  118.     char *user, identname[S5_USERNAME_SIZE];
  119.     S5NetAddr tmp, *dst;
  120.     S5IOHandle fd;
  121.     int len;
  122.     if (*idtentry != '') {
  123. RemoveIdentEntry(idtentry);
  124.     }
  125.     if (linkinfo->peerAuth == AUTH_NONE || IdentQuery(in, identname) < 0) {
  126. user = linkinfo->srcUser;
  127.     } else {
  128. user = identname;
  129.     }
  130.     if (!strlen(user)) {
  131. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Ident: Not recording ident info for empty username");
  132. return;
  133.     }
  134.     if (linkinfo->nextVersion) {
  135. dst = &linkinfo->sckAddr;
  136.     } else {
  137. dst = &linkinfo->dstAddr;
  138.     }
  139.     len = sizeof(S5NetAddr);
  140.     memset(&tmp, 0, len);
  141.     getsockname(out, &tmp.sa, &len);
  142.     sprintf(idtentry, "%s,%d,", ADDRANDPORT(dst));
  143.     sprintf(idtentry+strlen(idtentry), "%s,%d,", ADDRANDPORT(&tmp));
  144.     sprintf(idtentry+strlen(idtentry), "%sn",   user);
  145.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Ident: Recording ident info for user: %s", user);
  146.     if ((fd = openidtfile()) == S5InvalidIOHandle) return;
  147.     WRITEFILE(fd, idtentry, strlen(idtentry));
  148.     close(fd);
  149.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Ident: Ident info recorded");
  150. #endif
  151. }