xschpass.c
上传用户:lampled
上传日期:2007-01-07
资源大小:94k
文件大小:6k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /* Copyright (C) 1995, 1996 by Sven Berkvens (sven@stack.nl) */
  2. #include "config.h"
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #ifndef NONEWSTYLE
  7. #include <stdarg.h>
  8. #else /* Not not NONEWSTYLE */
  9. #include <varargs.h>
  10. #endif /* NONEWSTYLE */
  11. #include <sys/stat.h>
  12. #include <errno.h>
  13. #include <ctype.h>
  14. #include "extra.h"
  15. #include "xscrypt.h"
  16. #include "string.h"
  17. #ifndef NOFORWARDS
  18. static VOID error PROTO((const char *, ...));
  19. static VOID urldecode PROTO((char *));
  20. static VOID changepasswd PROTO((const char *, int));
  21. static VOID generateform PROTO((void));
  22. extern int main PROTO((int, char *[]));
  23. #endif /* NOFORWARDS */
  24. #ifndef NONEWSTYLE
  25. static VOID
  26. error(const char *format, ...)
  27. {
  28. va_list ap;
  29. va_start(ap, format);
  30. #else /* Not not NONEWSTYLE */
  31. static VOID
  32. error(format, va_alist)
  33. const char *format;
  34. va_dcl
  35. {
  36. va_list ap;
  37. va_start(ap);
  38. #endif /* NONEWSTYLE */
  39. alarm(180);
  40. printf("Content-type: text/htmlnn");
  41. printf("<HTML><HEAD><TITLE>");
  42. vprintf(format, ap);
  43. printf("</TITLE></HEAD>n<BODY>n<H1>");
  44. vprintf(format, ap);
  45. printf("</H1>n");
  46. vprintf(format, ap);
  47. printf("</BODY></HTML>n");
  48. va_end(ap);
  49. exit(1);
  50. }
  51. static VOID
  52. urldecode DECL1(char *, what)
  53. {
  54. static const char *hexdigits = "0123456789ABCDEF";
  55. const char *d1, *d2;
  56. while (*what)
  57. {
  58. if (*what == '+')
  59. *what = ' ';
  60. if (*what == '&')
  61. *what = 0;
  62. if (*what == '%')
  63. {
  64. if ((d1 = strchr(hexdigits, toupper(what[1]))) &&
  65.     (d2 = strchr(hexdigits, toupper(what[2]))))
  66. {
  67. *what = (d1-hexdigits)*16 + (d2-hexdigits);
  68. bcopy(what+3, what+1, strlen(what)-2);
  69. }
  70. }
  71. what++;
  72. }
  73. *(++what) = 0;
  74. }
  75. static VOID
  76. changepasswd DECL2C_(char *, param, int,  cl)
  77. {
  78. char filename[XS_PATH_MAX], username[BUFSIZ], old[BUFSIZ],
  79. new1[BUFSIZ], new2[BUFSIZ], buffer[BUFSIZ], *search,
  80. *search2;
  81. struct stat statbuf1, statbuf2;
  82. FILE *input, *output;
  83. int found;
  84. alarm(120); filename[0] = '/';
  85. strncpy(filename + 1, param, XS_PATH_MAX - 64);
  86. filename[XS_PATH_MAX - 65] = 0;
  87. if (cl > (BUFSIZ - 64))
  88. error("400 Too much input from your browser (%d bytes)", cl);
  89. if (read(0, buffer, cl) != cl)
  90. error("400 Invalid content length");
  91. buffer[cl] = 0;
  92. urldecode(buffer);
  93. username[0] = old[0] = new1[0] = new2[0] = 0;
  94. search = buffer;
  95. while (*search)
  96. {
  97. for (search2 = search; *search2; search2++) ;
  98. if (!strncasecmp("username=", search, 9))
  99. strcpy(username, search + 9);
  100. else if (!strncasecmp("old=", search, 4))
  101. strcpy(old, search + 4);
  102. else if (!strncasecmp("new1=", search, 5))
  103. strcpy(new1, search + 5);
  104. else if (!strncasecmp("new2=", search, 5))
  105. strcpy(new2, search + 5);
  106. else
  107. {
  108. strtok(search, "=");
  109. error("404 Unknown field '%s'", search);
  110. }
  111. search = search2 + 1;
  112. }
  113. if (!username[0] || !old[0] || !new1[0] || !new2[0])
  114. error("403 Not all fields were filled in correctly!");
  115. if (strcmp(new1, new2))
  116. error("403 You did not type the new password correctly two times!");
  117. xs_encrypt(new1); xs_encrypt(old);
  118. if (lstat(filename, &statbuf1))
  119. error("403 Could not lstat directory '%s': %s",
  120. filename, strerror(errno));
  121. if ((statbuf1.st_mode & S_IFMT) != S_IFDIR)
  122. error("403 '%s' is not a directory", filename);
  123. strcat(filename, "/");
  124. strcat(filename, AUTHFILE);
  125. if (lstat(filename, &statbuf2))
  126. error("403 Could not lstat password file '%s': %s",
  127. filename, strerror(errno));
  128. if ((statbuf2.st_mode & S_IFMT) != S_IFREG)
  129. error("403 Password file is not a regular file");
  130. if (statbuf1.st_uid != statbuf2.st_uid)
  131. error("403 File and directory user ID's do not match");
  132. if (!statbuf1.st_uid)
  133. error("403 Directory is owned by root");
  134. if (!(input = fopen(filename, "r")))
  135. error("403 Could not fopen password file '%s': %s",
  136. filename, strerror(errno));
  137. strcat(filename, ".new");
  138. if (!lstat(filename, &statbuf2))
  139. error("403 Somebody is already changing a password, please retry again in a few moments!");
  140. if (!(output = fopen(filename, "w")))
  141. error("403 Could not fopen new password file '%s': %s",
  142. filename, strerror(errno));
  143. if (chown(filename, statbuf1.st_uid, statbuf1.st_gid))
  144. error("403 Could not chown new password file '%s': %s",
  145. filename, strerror(errno));
  146. found = 0;
  147. sprintf(new2, "%s:%sn", username, old);
  148. while (fgets(buffer, BUFSIZ, input))
  149. {
  150. if (!found && !strcmp(buffer+1, new2))
  151. {
  152. found = 1;
  153. if (buffer[0] != 'U')
  154. {
  155. fclose(input); fclose(output);
  156. remove(filename);
  157. error("403 Password is locked");
  158. }
  159. fprintf(output, "%c%s:%sn",
  160. buffer[0], username, new1);
  161. } else
  162. fprintf(output, "%s", buffer);
  163. }
  164. fclose(input); fclose(output);
  165. if (!found)
  166. {
  167. remove(filename);
  168. error("403 Old username/password combination not found");
  169. }
  170. strcpy(buffer, filename);
  171. buffer[strlen(buffer) - 4] = 0;
  172. if (rename(filename, buffer))
  173. error("500 Could not rename '%s' to '%s': %s",
  174. filename, buffer, strerror(errno));
  175. printf("Content-type: text/htmlnn");
  176. printf("<HTML><HEAD><TITLE>Password changed</TITLE></HEAD>n");
  177. printf("<BODY><H1>Password changed</H1>n");
  178. printf("The password has been changed!</BODY></HTML>n");
  179. }
  180. static VOID
  181. generateform DECL0
  182. {
  183. alarm(180);
  184. printf("Content-type: text/htmlnn");
  185. printf("<HTML><HEAD><TITLE>Change password</TITLE></HEAD>n");
  186. printf("<BODY><H1>Change password</H1><PRE>n");
  187. printf("<FORM METHOD="POST" ACTION="%s%s">n",
  188. getenv("SCRIPT_NAME"), getenv("PATH_INFO"));
  189. printf("User name:      <INPUT NAME="username" TYPE="text" MAXLENGTH=16 SIZE=16><P>n");
  190. printf("Old password:   <INPUT NAME="old" TYPE="password" MAXLENGTH=16 SIZE=16><P>n");
  191. printf("New password:   <INPUT NAME="new1" TYPE="password" MAXLENGTH=16 SIZE=16><P>n");
  192. printf("Enter it again: <INPUT NAME="new2" TYPE="password" MAXLENGTH=16 SIZE=16><P>n");
  193. printf("<INPUT TYPE="submit" VALUE="Change password"> |n");
  194. printf("<INPUT TYPE="reset" VALUE="Clear form">n</FORM>");
  195. printf("</PRE></BODY></HTML>n");
  196. }
  197. extern int
  198. main DECL2(int, argc, char **, argv)
  199. {
  200. const char *param, *cl;
  201. int length;
  202. if (geteuid())
  203. error("501 Incorrect user ID for operation");
  204. if (!(param = getenv("PATH_TRANSLATED")))
  205. error("404 Incorrect usage - supply directory name");
  206. while (*param == '/')
  207. param++;
  208. cl = getenv("CONTENT_LENGTH");
  209. if (cl && ((length = atoi(cl)) > 0))
  210. changepasswd(param, length);
  211. else
  212. generateform();
  213. exit(0);
  214. }