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

代理服务器

开发平台:

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: upwd.c,v 1.38.4.3 1998/10/09 16:14:14 steve Exp $
  8.  */
  9. #include "socks5p.h"
  10. #include "buffer.h"
  11. #include "threads.h"
  12. #include "confutil.h"
  13. #include "addr.h"
  14. #include "msg.h"
  15. #include "log.h"
  16. #ifdef USE_PASSWD
  17. #ifdef HAVE_CRYPT_H
  18. #include <crypt.h>
  19. #endif
  20. #endif
  21. #ifdef USE_SHADOW_PASSWD
  22. #include <shadow.h>
  23. #ifdef HAVE_CRYPT_H
  24. #include <crypt.h>
  25. #endif
  26. #endif
  27. #define RESP_OFFSET    1
  28. #define ULEN_OFFSET(x) 1
  29. #define USER_OFFSET(x) 2
  30. #define PLEN_OFFSET(x) USER_OFFSET((x))+(x)[ULEN_OFFSET((x))]
  31. #define PSWD_OFFSET(x) PLEN_OFFSET((x))+1
  32. #define SETVERS(x, y) ((x)[0] = (y))
  33. #define SETULEN(x, y) ((x)[ULEN_OFFSET(x)] = ((y)?(u_char)strlen((y)):0))
  34. #define SETPLEN(x, y) ((x)[PLEN_OFFSET(x)] = ((y)?(u_char)strlen((y)):0))
  35. #define SETUSER(x, y) if ((y)) strcpy((x)+USER_OFFSET((x)), (y));
  36. #define SETPSWD(x, y) if ((y)) strcpy((x)+PSWD_OFFSET((x)), (y));
  37. #define GETRESP(x)    ((u_char)(x[RESP_OFFSET]))
  38. #define PASSWDHDRSIZE(x) PSWD_OFFSET((x))+(x)[PLEN_OFFSET((x))]
  39. #define PASSWDRSPSIZE    2
  40. #ifndef UPWD_TIMEOUT
  41. #define UPWD_TIMEOUT 15
  42. #endif
  43. #define UPWD_IOFLAGS S5_IOFLAGS_RESTART|S5_IOFLAGS_TIMED|S5_IOFLAGS_NBYTES
  44. char *lsUpwdDefaultFilename = SRVPWD_FILE;
  45. char *lsUpwdDefaultEnvname  = "SOCKS5_PWDFILE";
  46. IFTHREADED(extern MUTEX_T env_mutex;)
  47. static int GetString(S5IOHandle fd, char *buf, double *timerm) {
  48.     u_char len;
  49.     buf[0] = '';
  50.     if (S5IORecv(fd, NULL, (char *)&len, 1, 0, UPWD_IOFLAGS, timerm) != 1) return -1;
  51.     if (len == 0) return 0;
  52.     if (S5IORecv(fd, NULL, buf, len, 0, UPWD_IOFLAGS, timerm) != len) return -1;
  53.     buf[len] = '';
  54.     return len;
  55. }
  56. int lsPasswdCliAuth(S5IOHandle fd, S5AuthInfo *ainfo, char *user) {
  57.     double timerm = (double)UPWD_TIMEOUT;
  58.     char buf[2*255+3], *pwd;
  59.     char *tmp;
  60.     MUTEX_LOCK(env_mutex);
  61.     if ((tmp = getenv("SOCKS5_USER"))) user = tmp;
  62.     pwd = getenv("SOCKS5_PASSWD");
  63.     MUTEX_UNLOCK(env_mutex);
  64.     SETVERS(buf, 1);
  65.     SETULEN(buf, user);
  66.     SETUSER(buf, user);
  67.     SETPLEN(buf, pwd);
  68.     SETPSWD(buf, pwd);
  69.     if (S5IOSend(fd, NULL, buf, PASSWDHDRSIZE(buf), 0, UPWD_IOFLAGS, &timerm) != PASSWDHDRSIZE(buf)) return AUTH_FAIL;
  70.     if (S5IORecv(fd, NULL, buf, PASSWDRSPSIZE,      0, UPWD_IOFLAGS, &timerm) != PASSWDRSPSIZE)      return AUTH_FAIL;
  71.     return (GETRESP(buf) == 0x00)?AUTH_OK:AUTH_FAIL;
  72. }
  73. int lsPasswdSrvAuth(S5IOHandle sd, S5AuthInfo *ainfo, char *name) {
  74.     char resp[] = { 0x01, (char)0xff }, ver, passwd[256];
  75.     double timerm = UPWD_TIMEOUT;
  76.     int rval = AUTH_FAIL;
  77.     
  78.     IFTHREADED(static MUTEX_T upwd_mutex = MUTEX_INITIALIZER;)
  79.     MUTEX_LOCK(upwd_mutex);
  80.     if (S5IORecv(sd, NULL, &ver, 1, 0, UPWD_IOFLAGS, &timerm) != 1) {
  81. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Failed to receive version number");
  82. goto done;
  83.     }
  84.     if ((u_char)ver != 0x01) {
  85. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Incorrect version number: %d", ver);
  86. goto done;
  87.     }
  88.     
  89.     if (GetString(sd, name, &timerm) < 0) {
  90. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Failed to get valid username");
  91. goto done;
  92.     }
  93.     
  94.     if (GetString(sd, passwd, &timerm) < 0) {
  95. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Failed to get valid password");
  96. goto done;
  97.     }
  98. #ifdef  USE_PASSWD
  99.     {
  100. struct passwd *pw = getpwnam(name);
  101. if (pw == NULL || pw->pw_uid == 0) {
  102.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: No Password entry for user: %s", name);
  103.     goto done;
  104. }
  105. if (pw->pw_passwd && strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd)) {
  106.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Password incorrect for user: %s", name);
  107.     goto done;
  108. }
  109.     }
  110. #else
  111. #ifdef  USE_SHADOW_PASSWD
  112.     {
  113. struct spwd *pw = getspnam(name);
  114. if (pw == NULL) {
  115.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: No Shadow Password entry for user: %s", name);
  116.     goto done;
  117. }
  118. if (pw->sp_pwdp && strcmp(crypt(passwd, pw->sp_pwdp),pw->sp_pwdp)) {
  119.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Shadow Password incorrect for user: %s", name);
  120.     goto done;
  121. }
  122.     }
  123. #else
  124.     {
  125. char c, *myfile, *tmp, *tmpname, *tmppasswd;
  126. static char *buf = NULL;
  127. struct stat sb;
  128. S5IOHandle fd;
  129. if (buf) goto findname;
  130. MUTEX_LOCK(env_mutex);
  131. myfile = getenv(lsUpwdDefaultEnvname);
  132. myfile = myfile?myfile:lsUpwdDefaultFilename;
  133. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Password file is %s", myfile);
  134. fd = open(myfile, O_RDONLY);
  135. MUTEX_UNLOCK(env_mutex);
  136. /* No passwd file probably means you don't car about having passwds  */
  137. if (fd == S5InvalidIOHandle) {
  138.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Error opening password file: %m");
  139.     goto done;
  140. }
  141. /* Fstat to see how big a buffer we should allocated...what would    */
  142. /* cause this to fail?  Either way, if it does, bail.                */
  143. if (fstat(fd, &sb) < 0) {
  144.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Error stating open password file: %m");
  145.     REAL(close)(fd);
  146.     goto done;
  147. }
  148. /* If we can't allocate a buffer as big as the password file itself, */
  149. /* bail...                                                           */
  150. if ((buf = (char *)malloc((sb.st_size+1)*sizeof(char))) == NULL) {
  151.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Malloc failed for password file");
  152.     REAL(close)(fd);
  153.     goto done;
  154. }
  155. /* Read in the contents of the file...                               */
  156. if (READFILE(fd, buf, sb.st_size) < 0) {
  157.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Error reading open password file: %m");
  158.     free(buf); buf = NULL;
  159.     REAL(close)(fd);
  160.     goto done;
  161. }
  162. buf[sb.st_size] = '';
  163. REAL(close)(fd);
  164.       findname:
  165. for (tmp = buf ; tmp; tmp = strchr(tmp, 'n'), tmp = tmp?tmp+1:NULL) {
  166.     tmpname = tmp;
  167.     while ((*tmpname != 'n') && isspace(*tmpname)) tmpname++;
  168.     if (*tmpname == 'n') continue;
  169.     tmppasswd = tmpname;
  170.     while ((*tmppasswd != 'n') && !isspace(*tmppasswd)) tmppasswd++;
  171.     if (*tmppasswd == 'n') continue;
  172.     c = *tmppasswd;
  173.     *tmppasswd = '';
  174.     if (strcmp(tmpname, name) != 0) {
  175. *tmppasswd = c;
  176. continue;
  177.     }
  178.     *tmppasswd = c;
  179.     while ((*tmppasswd != 'n') && isspace(*tmppasswd)) tmppasswd++;
  180.     if (*tmppasswd == 'n') continue;
  181.     tmpname = tmppasswd;
  182.     while (!isspace(*tmpname)) tmpname++;
  183.     c = *tmpname;
  184.     *tmpname = '';
  185.     if (strcmp(tmppasswd, passwd) != 0) {
  186. *tmpname = c;
  187. continue;
  188.     }
  189.     *tmpname = c;
  190.     break;
  191. }
  192. if (!tmp) {
  193.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: User: %s no match in password file", name);
  194.     goto done;
  195. }
  196.     }
  197. #endif /* USE_SHADOW_PASSWD */
  198. #endif  /* USE_PASSWD        */
  199.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: successful: user is %s", name);
  200.     rval = AUTH_OK;
  201.     
  202.   done:
  203.     MUTEX_UNLOCK(upwd_mutex);
  204.     if (rval == AUTH_OK) resp[1] = 0x00;
  205.     memset(passwd, 0, sizeof(passwd));
  206.     
  207.     if (S5IOSend(sd, NULL, resp, sizeof(resp), 0, UPWD_IOFLAGS, &timerm) != sizeof(resp)) {
  208. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UPWD: Failed to send response to client");
  209. return AUTH_FAIL;
  210.     }
  211.     
  212.     return rval;
  213. }