📄 htpasswd.c
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//****************************************************************************** ****************************************************************************** * NOTE! This program is not safe as a setuid executable! Do not make it * setuid! ****************************************************************************** *****************************************************************************//* * htpasswd.c: simple program for manipulating password file for * the Apache HTTP server * * Originally by Rob McCool * * Exit values: * 0: Success * 1: Failure; file access/permission problem * 2: Failure; command line syntax problem (usage message issued) * 3: Failure; password verification failure * 4: Failure; operation interrupted (such as with CTRL/C) * 5: Failure; buffer would overflow (username, filename, or computed * record too long) * 6: Failure; username contains illegal or reserved characters * 7: Failure; file is not a valid htpasswd file */#include "apr.h"#include "apr_lib.h"#include "apr_strings.h"#include "apr_errno.h"#include "apr_file_io.h"#include "apr_general.h"#include "apr_signal.h"#if APR_HAVE_STDIO_H#include <stdio.h>#endif#include "apr_md5.h"#include "apr_sha1.h"#include <time.h>#if APR_HAVE_CRYPT_H#include <crypt.h>#endif#if APR_HAVE_STDLIB_H#include <stdlib.h>#endif#if APR_HAVE_STRING_H#include <string.h>#endif#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#ifdef WIN32#include <conio.h>#define unlink _unlink#endif#if !APR_CHARSET_EBCDIC#define LF 10#define CR 13#else /*APR_CHARSET_EBCDIC*/#define LF '\n'#define CR '\r'#endif /*APR_CHARSET_EBCDIC*/#define MAX_STRING_LEN 256#define ALG_PLAIN 0#define ALG_CRYPT 1#define ALG_APMD5 2#define ALG_APSHA 3 #define ERR_FILEPERM 1#define ERR_SYNTAX 2#define ERR_PWMISMATCH 3#define ERR_INTERRUPTED 4#define ERR_OVERFLOW 5#define ERR_BADUSER 6#define ERR_INVALID 7#define APHTP_NEWFILE 1#define APHTP_NOFILE 2#define APHTP_NONINTERACTIVE 4#define APHTP_DELUSER 8apr_file_t *errfile;apr_file_t *ftemp = NULL;static void to64(char *s, unsigned long v, int n){ static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; }}static void putline(apr_file_t *f, const char *l){ apr_file_puts(l, f);}/* * Make a password record from the given information. A zero return * indicates success; failure means that the output buffer contains an * error message instead. */static int mkrecord(char *user, char *record, apr_size_t rlen, char *passwd, int alg){ char *pw; char cpw[120]; char pwin[MAX_STRING_LEN]; char pwv[MAX_STRING_LEN]; char salt[9]; apr_size_t bufsize; if (passwd != NULL) { pw = passwd; } else { bufsize = sizeof(pwin); if (apr_password_get("New password: ", pwin, &bufsize) != 0) { apr_snprintf(record, (rlen - 1), "password too long (>%" APR_SIZE_T_FMT ")", sizeof(pwin) - 1); return ERR_OVERFLOW; } bufsize = sizeof(pwv); apr_password_get("Re-type new password: ", pwv, &bufsize); if (strcmp(pwin, pwv) != 0) { apr_cpystrn(record, "password verification error", (rlen - 1)); return ERR_PWMISMATCH; } pw = pwin; memset(pwv, '\0', sizeof(pwin)); } switch (alg) { case ALG_APSHA: /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */ apr_sha1_base64(pw,strlen(pw),cpw); break; case ALG_APMD5: (void) srand((int) time((time_t *) NULL)); to64(&salt[0], rand(), 8); salt[8] = '\0'; apr_md5_encode((const char *)pw, (const char *)salt, cpw, sizeof(cpw)); break; case ALG_PLAIN: /* XXX this len limitation is not in sync with any HTTPd len. */ apr_cpystrn(cpw,pw,sizeof(cpw)); break;#if !(defined(WIN32) || defined(NETWARE)) case ALG_CRYPT: default: (void) srand((int) time((time_t *) NULL)); to64(&salt[0], rand(), 8); salt[8] = '\0'; apr_cpystrn(cpw, (char *)crypt(pw, salt), sizeof(cpw) - 1); break;#endif } memset(pw, '\0', strlen(pw)); /* * Check to see if the buffer is large enough to hold the username, * hash, and delimiters. */ if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) { apr_cpystrn(record, "resultant record too long", (rlen - 1)); return ERR_OVERFLOW; } strcpy(record, user); strcat(record, ":"); strcat(record, cpw); strcat(record, "\n"); return 0;}static void usage(void){ apr_file_printf(errfile, "Usage:\n"); apr_file_printf(errfile, "\thtpasswd [-cmdpsD] passwordfile username\n"); apr_file_printf(errfile, "\thtpasswd -b[cmdpsD] passwordfile username " "password\n\n"); apr_file_printf(errfile, "\thtpasswd -n[mdps] username\n"); apr_file_printf(errfile, "\thtpasswd -nb[mdps] username password\n"); apr_file_printf(errfile, " -c Create a new file.\n"); apr_file_printf(errfile, " -n Don't update file; display results on " "stdout.\n"); apr_file_printf(errfile, " -m Force MD5 encryption of the password"#if defined(WIN32) || defined(TPF) || defined(NETWARE) " (default)"#endif ".\n"); apr_file_printf(errfile, " -d Force CRYPT encryption of the password"#if (!(defined(WIN32) || defined(TPF) || defined(NETWARE))) " (default)"#endif ".\n"); apr_file_printf(errfile, " -p Do not encrypt the password (plaintext).\n"); apr_file_printf(errfile, " -s Force SHA encryption of the password.\n"); apr_file_printf(errfile, " -b Use the password from the command line " "rather than prompting for it.\n"); apr_file_printf(errfile, " -D Delete the specified user.\n"); apr_file_printf(errfile, "On Windows, NetWare and TPF systems the '-m' flag is used by " "default.\n"); apr_file_printf(errfile, "On all other systems, the '-p' flag will probably not work.\n"); exit(ERR_SYNTAX);}/* * Check to see if the specified file can be opened for the given * access. */static int accessible(apr_pool_t *pool, char *fname, int mode){ apr_file_t *f = NULL; if (apr_file_open(&f, fname, mode, APR_OS_DEFAULT, pool) != APR_SUCCESS) { return 0; } apr_file_close(f); return 1;}/* * Return true if the named file exists, regardless of permissions. */static int exists(char *fname, apr_pool_t *pool){ apr_finfo_t sbuf; apr_status_t check; check = apr_stat(&sbuf, fname, APR_FINFO_TYPE, pool); return ((check || sbuf.filetype != APR_REG) ? 0 : 1);}static void terminate(void){ apr_terminate();#ifdef NETWARE pressanykey();#endif}static void check_args(apr_pool_t *pool, int argc, const char *const argv[], int *alg, int *mask, char **user, char **pwfilename, char **password){ const char *arg; int args_left = 2; int i; /* * Preliminary check to make sure they provided at least * three arguments, we'll do better argument checking as * we parse the command line. */ if (argc < 3) { usage(); } /* * Go through the argument list and pick out any options. They * have to precede any other arguments. */ for (i = 1; i < argc; i++) { arg = argv[i]; if (*arg != '-') { break; } while (*++arg != '\0') { if (*arg == 'c') { *mask |= APHTP_NEWFILE; } else if (*arg == 'n') { *mask |= APHTP_NOFILE; args_left--; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -