htdigest.c revision 0942697a9b5de44865676345a3828741c827efe6
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder/* ====================================================================
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * Redistribution and use in source and binary forms, with or without
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * modification, are permitted provided that the following conditions
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * are met:
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * 1. Redistributions of source code must retain the above copyright
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * notice, this list of conditions and the following disclaimer.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * 2. Redistributions in binary form must reproduce the above copyright
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * notice, this list of conditions and the following disclaimer in
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * the documentation and/or other materials provided with the
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * distribution.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * 3. All advertising materials mentioning features or use of this
bb4d3b6e93db1495f02de46aff5076862e30517bChristian Maeder * software must display the following acknowledgment:
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * "This product includes software developed by the Apache Group
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * for use in the Apache HTTP server project (http://www.apache.org/)."
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
bb4d3b6e93db1495f02de46aff5076862e30517bChristian Maeder * 4. The names "Apache Server" and "Apache Group" must not be used to
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * endorse or promote products derived from this software without
70e83495a9753d2a104a9869ac2a997ac30d05c1Christian Maeder * prior written permission. For written permission, please contact
bb4d3b6e93db1495f02de46aff5076862e30517bChristian Maeder * apache@apache.org.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * 5. Products derived from this software may not be called "Apache"
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * nor may "Apache" appear in their names without prior written
bb4d3b6e93db1495f02de46aff5076862e30517bChristian Maeder * permission of the Apache Group.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
21b18016469e574bd145ad07c7b0f02839677cc3Christian Maeder * 6. Redistributions of any form whatsoever must retain the following
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * acknowledgment:
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder * "This product includes software developed by the Apache Group
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder * for use in the Apache HTTP server project (http://www.apache.org/)."
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * OF THE POSSIBILITY OF SUCH DAMAGE.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * ====================================================================
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * This software consists of voluntary contributions made by many
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * individuals on behalf of the Apache Group and was originally based
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * on public domain software written at the National Center for
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * Supercomputing Applications, University of Illinois, Urbana-Champaign.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * For more information on the Apache Group and the Apache HTTP server
21b18016469e574bd145ad07c7b0f02839677cc3Christian Maeder * project, please see <http://www.apache.org/>.
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder */
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder/******************************************************************************
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder ******************************************************************************
7862e8fb34d79382e93b45ce894acdd928da8a51Christian Maeder * NOTE! This program is not safe as a setuid executable! Do not make it
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * setuid!
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder ******************************************************************************
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *****************************************************************************/
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder/*
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * htdigest.c: simple program for manipulating digest passwd file for Apache
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder *
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder * by Alexei Kosut, based on htpasswd.c, by Rob McCool
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder */
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder
7862e8fb34d79382e93b45ce894acdd928da8a51Christian Maeder#include "apr_lib.h"
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder#include "ap_config.h"
bb4d3b6e93db1495f02de46aff5076862e30517bChristian Maeder#include <sys/types.h>
bb4d3b6e93db1495f02de46aff5076862e30517bChristian Maeder#include "ap.h"
21b18016469e574bd145ad07c7b0f02839677cc3Christian Maeder#include "ap_md5.h"
21b18016469e574bd145ad07c7b0f02839677cc3Christian Maeder#if defined(MPE) || defined(QNX) || defined(WIN32) || defined(__TANDEM) || defined(BEOS)
70e83495a9753d2a104a9869ac2a997ac30d05c1Christian Maeder#include <signal.h>
70e83495a9753d2a104a9869ac2a997ac30d05c1Christian Maeder#else
7862e8fb34d79382e93b45ce894acdd928da8a51Christian Maeder#include <sys/signal.h>
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder#endif
cf7e0d6750e408ddb47545d6b8349a70cf0b47afChristian Maeder
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder#ifdef WIN32
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder#include <conio.h>
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder#define unlink _unlink
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder#endif
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder#ifdef CHARSET_EBCDIC
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder#define LF '\n'
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder#define CR '\r'
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder#else
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder#define LF 10
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder#define CR 13
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder#endif /* CHARSET_EBCDIC */
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder#define MAX_STRING_LEN 256
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maeder
e9490701e16d1e8abd995ef876d6f937da93b412Christian Maederchar *tn;
62d8627183cce49c052386186ad69c95b1aa3953Christian Maeder
static void getword(char *word, char *line, char stop)
{
int x = 0, y;
for (x = 0; ((line[x]) && (line[x] != stop)); x++)
word[x] = line[x];
word[x] = '\0';
if (line[x])
++x;
y = 0;
while ((line[y++] = line[x++]));
}
static int getline(char *s, int n, FILE *f)
{
register int i = 0;
while (1) {
s[i] = (char) fgetc(f);
if (s[i] == CR)
s[i] = fgetc(f);
if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
s[i] = '\0';
return (feof(f) ? 1 : 0);
}
++i;
}
}
static void putline(FILE *f, char *l)
{
int x;
for (x = 0; l[x]; x++)
fputc(l[x], f);
fputc('\n', f);
}
static void add_password(char *user, char *realm, FILE *f)
{
char *pw;
AP_MD5_CTX context;
unsigned char digest[16];
char string[MAX_STRING_LEN];
char pwin[MAX_STRING_LEN];
char pwv[MAX_STRING_LEN];
unsigned int i;
size_t bufsize;
bufsize = sizeof(pwin);
if (ap_getpass("New password: ", pwin, &bufsize) != 0) {
fprintf(stderr, "password too long");
exit(5);
}
bufsize = sizeof(pwv);
ap_getpass("Re-type new password: ", pwv, &bufsize);
if (strcmp(pwin, pwv) != 0) {
fprintf(stderr, "They don't match, sorry.\n");
if (tn) {
unlink(tn);
}
exit(1);
}
pw = pwin;
fprintf(f, "%s:%s:", user, realm);
/* Do MD5 stuff */
sprintf(string, "%s:%s:%s", user, realm, pw);
ap_MD5Init(&context);
ap_MD5Update(&context, (unsigned char *) string, strlen(string));
ap_MD5Final(digest, &context);
for (i = 0; i < 16; i++)
fprintf(f, "%02x", digest[i]);
fprintf(f, "\n");
}
static void usage(void)
{
fprintf(stderr, "Usage: htdigest [-c] passwordfile realm username\n");
fprintf(stderr, "The -c flag creates a new file.\n");
exit(1);
}
static void interrupted(void)
{
fprintf(stderr, "Interrupted.\n");
if (tn)
unlink(tn);
exit(1);
}
int main(int argc, char *argv[])
{
FILE *tfp, *f;
char user[MAX_STRING_LEN];
char realm[MAX_STRING_LEN];
char line[MAX_STRING_LEN];
char l[MAX_STRING_LEN];
char w[MAX_STRING_LEN];
char x[MAX_STRING_LEN];
char command[MAX_STRING_LEN];
int found;
tn = NULL;
signal(SIGINT, (void (*)(int)) interrupted);
if (argc == 5) {
if (strcmp(argv[1], "-c"))
usage();
if (!(tfp = fopen(argv[2], "w"))) {
fprintf(stderr, "Could not open passwd file %s for writing.\n",
argv[2]);
perror("fopen");
exit(1);
}
printf("Adding password for %s in realm %s.\n", argv[4], argv[3]);
add_password(argv[4], argv[3], tfp);
fclose(tfp);
exit(0);
}
else if (argc != 4)
usage();
tn = tmpnam(NULL);
if (!(tfp = fopen(tn, "w"))) {
fprintf(stderr, "Could not open temp file.\n");
exit(1);
}
if (!(f = fopen(argv[1], "r"))) {
fprintf(stderr,
"Could not open passwd file %s for reading.\n", argv[1]);
fprintf(stderr, "Use -c option to create new one.\n");
exit(1);
}
strcpy(user, argv[3]);
strcpy(realm, argv[2]);
found = 0;
while (!(getline(line, MAX_STRING_LEN, f))) {
if (found || (line[0] == '#') || (!line[0])) {
putline(tfp, line);
continue;
}
strcpy(l, line);
getword(w, l, ':');
getword(x, l, ':');
if (strcmp(user, w) || strcmp(realm, x)) {
putline(tfp, line);
continue;
}
else {
printf("Changing password for user %s in realm %s\n", user, realm);
add_password(user, realm, tfp);
found = 1;
}
}
if (!found) {
printf("Adding user %s in realm %s\n", user, realm);
add_password(user, realm, tfp);
}
fclose(f);
fclose(tfp);
#if defined(OS2) || defined(WIN32)
sprintf(command, "copy \"%s\" \"%s\"", tn, argv[1]);
#else
sprintf(command, "cp %s %s", tn, argv[1]);
#endif
system(command);
unlink(tn);
return 0;
}