xschpass.c
资源名称:httpd.tar.gz [点击查看]
上传用户:lampled
上传日期:2007-01-07
资源大小:94k
文件大小:6k
源码类别:
Web服务器
开发平台:
Unix_Linux
- /* Copyright (C) 1995, 1996 by Sven Berkvens (sven@stack.nl) */
- #include "config.h"
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #ifndef NONEWSTYLE
- #include <stdarg.h>
- #else /* Not not NONEWSTYLE */
- #include <varargs.h>
- #endif /* NONEWSTYLE */
- #include <sys/stat.h>
- #include <errno.h>
- #include <ctype.h>
- #include "extra.h"
- #include "xscrypt.h"
- #include "string.h"
- #ifndef NOFORWARDS
- static VOID error PROTO((const char *, ...));
- static VOID urldecode PROTO((char *));
- static VOID changepasswd PROTO((const char *, int));
- static VOID generateform PROTO((void));
- extern int main PROTO((int, char *[]));
- #endif /* NOFORWARDS */
- #ifndef NONEWSTYLE
- static VOID
- error(const char *format, ...)
- {
- va_list ap;
- va_start(ap, format);
- #else /* Not not NONEWSTYLE */
- static VOID
- error(format, va_alist)
- const char *format;
- va_dcl
- {
- va_list ap;
- va_start(ap);
- #endif /* NONEWSTYLE */
- alarm(180);
- printf("Content-type: text/htmlnn");
- printf("<HTML><HEAD><TITLE>");
- vprintf(format, ap);
- printf("</TITLE></HEAD>n<BODY>n<H1>");
- vprintf(format, ap);
- printf("</H1>n");
- vprintf(format, ap);
- printf("</BODY></HTML>n");
- va_end(ap);
- exit(1);
- }
- static VOID
- urldecode DECL1(char *, what)
- {
- static const char *hexdigits = "0123456789ABCDEF";
- const char *d1, *d2;
- while (*what)
- {
- if (*what == '+')
- *what = ' ';
- if (*what == '&')
- *what = 0;
- if (*what == '%')
- {
- if ((d1 = strchr(hexdigits, toupper(what[1]))) &&
- (d2 = strchr(hexdigits, toupper(what[2]))))
- {
- *what = (d1-hexdigits)*16 + (d2-hexdigits);
- bcopy(what+3, what+1, strlen(what)-2);
- }
- }
- what++;
- }
- *(++what) = 0;
- }
- static VOID
- changepasswd DECL2C_(char *, param, int, cl)
- {
- char filename[XS_PATH_MAX], username[BUFSIZ], old[BUFSIZ],
- new1[BUFSIZ], new2[BUFSIZ], buffer[BUFSIZ], *search,
- *search2;
- struct stat statbuf1, statbuf2;
- FILE *input, *output;
- int found;
- alarm(120); filename[0] = '/';
- strncpy(filename + 1, param, XS_PATH_MAX - 64);
- filename[XS_PATH_MAX - 65] = 0;
- if (cl > (BUFSIZ - 64))
- error("400 Too much input from your browser (%d bytes)", cl);
- if (read(0, buffer, cl) != cl)
- error("400 Invalid content length");
- buffer[cl] = 0;
- urldecode(buffer);
- username[0] = old[0] = new1[0] = new2[0] = 0;
- search = buffer;
- while (*search)
- {
- for (search2 = search; *search2; search2++) ;
- if (!strncasecmp("username=", search, 9))
- strcpy(username, search + 9);
- else if (!strncasecmp("old=", search, 4))
- strcpy(old, search + 4);
- else if (!strncasecmp("new1=", search, 5))
- strcpy(new1, search + 5);
- else if (!strncasecmp("new2=", search, 5))
- strcpy(new2, search + 5);
- else
- {
- strtok(search, "=");
- error("404 Unknown field '%s'", search);
- }
- search = search2 + 1;
- }
- if (!username[0] || !old[0] || !new1[0] || !new2[0])
- error("403 Not all fields were filled in correctly!");
- if (strcmp(new1, new2))
- error("403 You did not type the new password correctly two times!");
- xs_encrypt(new1); xs_encrypt(old);
- if (lstat(filename, &statbuf1))
- error("403 Could not lstat directory '%s': %s",
- filename, strerror(errno));
- if ((statbuf1.st_mode & S_IFMT) != S_IFDIR)
- error("403 '%s' is not a directory", filename);
- strcat(filename, "/");
- strcat(filename, AUTHFILE);
- if (lstat(filename, &statbuf2))
- error("403 Could not lstat password file '%s': %s",
- filename, strerror(errno));
- if ((statbuf2.st_mode & S_IFMT) != S_IFREG)
- error("403 Password file is not a regular file");
- if (statbuf1.st_uid != statbuf2.st_uid)
- error("403 File and directory user ID's do not match");
- if (!statbuf1.st_uid)
- error("403 Directory is owned by root");
- if (!(input = fopen(filename, "r")))
- error("403 Could not fopen password file '%s': %s",
- filename, strerror(errno));
- strcat(filename, ".new");
- if (!lstat(filename, &statbuf2))
- error("403 Somebody is already changing a password, please retry again in a few moments!");
- if (!(output = fopen(filename, "w")))
- error("403 Could not fopen new password file '%s': %s",
- filename, strerror(errno));
- if (chown(filename, statbuf1.st_uid, statbuf1.st_gid))
- error("403 Could not chown new password file '%s': %s",
- filename, strerror(errno));
- found = 0;
- sprintf(new2, "%s:%sn", username, old);
- while (fgets(buffer, BUFSIZ, input))
- {
- if (!found && !strcmp(buffer+1, new2))
- {
- found = 1;
- if (buffer[0] != 'U')
- {
- fclose(input); fclose(output);
- remove(filename);
- error("403 Password is locked");
- }
- fprintf(output, "%c%s:%sn",
- buffer[0], username, new1);
- } else
- fprintf(output, "%s", buffer);
- }
- fclose(input); fclose(output);
- if (!found)
- {
- remove(filename);
- error("403 Old username/password combination not found");
- }
- strcpy(buffer, filename);
- buffer[strlen(buffer) - 4] = 0;
- if (rename(filename, buffer))
- error("500 Could not rename '%s' to '%s': %s",
- filename, buffer, strerror(errno));
- printf("Content-type: text/htmlnn");
- printf("<HTML><HEAD><TITLE>Password changed</TITLE></HEAD>n");
- printf("<BODY><H1>Password changed</H1>n");
- printf("The password has been changed!</BODY></HTML>n");
- }
- static VOID
- generateform DECL0
- {
- alarm(180);
- printf("Content-type: text/htmlnn");
- printf("<HTML><HEAD><TITLE>Change password</TITLE></HEAD>n");
- printf("<BODY><H1>Change password</H1><PRE>n");
- printf("<FORM METHOD="POST" ACTION="%s%s">n",
- getenv("SCRIPT_NAME"), getenv("PATH_INFO"));
- printf("User name: <INPUT NAME="username" TYPE="text" MAXLENGTH=16 SIZE=16><P>n");
- printf("Old password: <INPUT NAME="old" TYPE="password" MAXLENGTH=16 SIZE=16><P>n");
- printf("New password: <INPUT NAME="new1" TYPE="password" MAXLENGTH=16 SIZE=16><P>n");
- printf("Enter it again: <INPUT NAME="new2" TYPE="password" MAXLENGTH=16 SIZE=16><P>n");
- printf("<INPUT TYPE="submit" VALUE="Change password"> |n");
- printf("<INPUT TYPE="reset" VALUE="Clear form">n</FORM>");
- printf("</PRE></BODY></HTML>n");
- }
- extern int
- main DECL2(int, argc, char **, argv)
- {
- const char *param, *cl;
- int length;
- if (geteuid())
- error("501 Incorrect user ID for operation");
- if (!(param = getenv("PATH_TRANSLATED")))
- error("404 Incorrect usage - supply directory name");
- while (*param == '/')
- param++;
- cl = getenv("CONTENT_LENGTH");
- if (cl && ((length = atoi(cl)) > 0))
- changepasswd(param, length);
- else
- generateform();
- exit(0);
- }