00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "apr.h"
00030 #include "apr_file_io.h"
00031 #include "apr_md5.h"
00032 #include "apr_lib.h"
00033 #include "apr_general.h"
00034 #include "apr_signal.h"
00035 #include "apr_strings.h"
00036
00037 #define APR_WANT_STDIO
00038 #define APR_WANT_STRFUNC
00039 #include "apr_want.h"
00040
00041 #if APR_HAVE_SYS_TYPES_H
00042 #include <sys/types.h>
00043 #endif
00044 #if APR_HAVE_STDLIB_H
00045 #include <stdlib.h>
00046 #endif
00047
00048 #ifdef WIN32
00049 #include <conio.h>
00050 #endif
00051
00052
00053 #if APR_CHARSET_EBCDIC
00054 #define LF '\n'
00055 #define CR '\r'
00056 #else
00057 #define LF 10
00058 #define CR 13
00059 #endif
00060
00061 #define MAX_STRING_LEN 256
00062
00063 apr_file_t *tfp = NULL;
00064 apr_file_t *errfile;
00065 apr_pool_t *cntxt;
00066 #if APR_CHARSET_EBCDIC
00067 apr_xlate_t *to_ascii;
00068 #endif
00069
00070 static void cleanup_tempfile_and_exit(int rc)
00071 {
00072 if (tfp) {
00073 apr_file_close(tfp);
00074 }
00075 exit(rc);
00076 }
00077
00078 static void getword(char *word, char *line, char stop)
00079 {
00080 int x = 0, y;
00081
00082 for (x = 0; ((line[x]) && (line[x] != stop)); x++)
00083 word[x] = line[x];
00084
00085 word[x] = '\0';
00086 if (line[x])
00087 ++x;
00088 y = 0;
00089
00090 while ((line[y++] = line[x++]));
00091 }
00092
00093 static int get_line(char *s, int n, apr_file_t *f)
00094 {
00095 register int i = 0;
00096 char ch;
00097 apr_status_t rv = APR_EINVAL;
00098
00099 while (i < (n - 1) &&
00100 ((rv = apr_file_getc(&ch, f)) == APR_SUCCESS) && (ch != '\n')) {
00101 s[i++] = ch;
00102 }
00103 if (ch == '\n')
00104 s[i++] = ch;
00105 s[i] = '\0';
00106
00107 if (rv != APR_SUCCESS)
00108 return 1;
00109
00110 return 0;
00111 }
00112
00113 static void putline(apr_file_t *f, char *l)
00114 {
00115 int x;
00116
00117 for (x = 0; l[x]; x++)
00118 apr_file_putc(l[x], f);
00119 }
00120
00121
00122 static void add_password(const char *user, const char *realm, apr_file_t *f)
00123 {
00124 char *pw;
00125 apr_md5_ctx_t context;
00126 unsigned char digest[16];
00127 char string[MAX_STRING_LEN];
00128 char pwin[MAX_STRING_LEN];
00129 char pwv[MAX_STRING_LEN];
00130 unsigned int i;
00131 apr_size_t len = sizeof(pwin);
00132
00133 if (apr_password_get("New password: ", pwin, &len) != APR_SUCCESS) {
00134 apr_file_printf(errfile, "password too long");
00135 cleanup_tempfile_and_exit(5);
00136 }
00137 len = sizeof(pwin);
00138 apr_password_get("Re-type new password: ", pwv, &len);
00139 if (strcmp(pwin, pwv) != 0) {
00140 apr_file_printf(errfile, "They don't match, sorry.\n");
00141 cleanup_tempfile_and_exit(1);
00142 }
00143 pw = pwin;
00144 apr_file_printf(f, "%s:%s:", user, realm);
00145
00146
00147 sprintf(string, "%s:%s:%s", user, realm, pw);
00148
00149 apr_md5_init(&context);
00150 #if APR_CHARSET_EBCDIC
00151 apr_md5_set_xlate(&context, to_ascii);
00152 #endif
00153 apr_md5_update(&context, (unsigned char *) string, strlen(string));
00154 apr_md5_final(digest, &context);
00155
00156 for (i = 0; i < 16; i++)
00157 apr_file_printf(f, "%02x", digest[i]);
00158
00159 apr_file_printf(f, "\n");
00160 }
00161
00162 static void usage(void)
00163 {
00164 apr_file_printf(errfile, "Usage: htdigest [-c] passwordfile realm username\n");
00165 apr_file_printf(errfile, "The -c flag creates a new file.\n");
00166 exit(1);
00167 }
00168
00169 static void interrupted(void)
00170 {
00171 apr_file_printf(errfile, "Interrupted.\n");
00172 cleanup_tempfile_and_exit(1);
00173 }
00174
00175 static void terminate(void)
00176 {
00177 apr_terminate();
00178 #ifdef NETWARE
00179 pressanykey();
00180 #endif
00181 }
00182
00183 int main(int argc, const char * const argv[])
00184 {
00185 apr_file_t *f;
00186 apr_status_t rv;
00187 char tn[] = "htdigest.tmp.XXXXXX";
00188 char *dirname;
00189 char user[MAX_STRING_LEN];
00190 char realm[MAX_STRING_LEN];
00191 char line[MAX_STRING_LEN];
00192 char l[MAX_STRING_LEN];
00193 char w[MAX_STRING_LEN];
00194 char x[MAX_STRING_LEN];
00195 int found;
00196
00197 apr_app_initialize(&argc, &argv, NULL);
00198 atexit(terminate);
00199 apr_pool_create(&cntxt, NULL);
00200 apr_file_open_stderr(&errfile, cntxt);
00201
00202 #if APR_CHARSET_EBCDIC
00203 rv = apr_xlate_open(&to_ascii, "ISO8859-1", APR_DEFAULT_CHARSET, cntxt);
00204 if (rv) {
00205 apr_file_printf(errfile, "apr_xlate_open(): %s (%d)\n",
00206 apr_strerror(rv, line, sizeof(line)), rv);
00207 exit(1);
00208 }
00209 #endif
00210
00211 apr_signal(SIGINT, (void (*)(int)) interrupted);
00212 if (argc == 5) {
00213 if (strcmp(argv[1], "-c"))
00214 usage();
00215 rv = apr_file_open(&f, argv[2], APR_WRITE | APR_CREATE,
00216 APR_OS_DEFAULT, cntxt);
00217 if (rv != APR_SUCCESS) {
00218 char errmsg[120];
00219
00220 apr_file_printf(errfile, "Could not open passwd file %s for writing: %s\n",
00221 argv[2],
00222 apr_strerror(rv, errmsg, sizeof errmsg));
00223 exit(1);
00224 }
00225 apr_file_printf(errfile, "Adding password for %s in realm %s.\n",
00226 argv[4], argv[3]);
00227 add_password(argv[4], argv[3], f);
00228 apr_file_close(f);
00229 exit(0);
00230 }
00231 else if (argc != 4)
00232 usage();
00233
00234 if (apr_temp_dir_get((const char**)&dirname, cntxt) != APR_SUCCESS) {
00235 apr_file_printf(errfile, "%s: could not determine temp dir\n",
00236 argv[0]);
00237 exit(1);
00238 }
00239 dirname = apr_psprintf(cntxt, "%s/%s", dirname, tn);
00240
00241 if (apr_file_mktemp(&tfp, dirname, 0, cntxt) != APR_SUCCESS) {
00242 apr_file_printf(errfile, "Could not open temp file %s.\n", dirname);
00243 exit(1);
00244 }
00245
00246 if (apr_file_open(&f, argv[1], APR_READ, APR_OS_DEFAULT, cntxt) != APR_SUCCESS) {
00247 apr_file_printf(errfile,
00248 "Could not open passwd file %s for reading.\n", argv[1]);
00249 apr_file_printf(errfile, "Use -c option to create new one.\n");
00250 cleanup_tempfile_and_exit(1);
00251 }
00252 apr_cpystrn(user, argv[3], sizeof(user));
00253 apr_cpystrn(realm, argv[2], sizeof(realm));
00254
00255 found = 0;
00256 while (!(get_line(line, MAX_STRING_LEN, f))) {
00257 if (found || (line[0] == '#') || (!line[0])) {
00258 putline(tfp, line);
00259 continue;
00260 }
00261 strcpy(l, line);
00262 getword(w, l, ':');
00263 getword(x, l, ':');
00264 if (strcmp(user, w) || strcmp(realm, x)) {
00265 putline(tfp, line);
00266 continue;
00267 }
00268 else {
00269 apr_file_printf(errfile, "Changing password for user %s in realm %s\n",
00270 user, realm);
00271 add_password(user, realm, tfp);
00272 found = 1;
00273 }
00274 }
00275 if (!found) {
00276 apr_file_printf(errfile, "Adding user %s in realm %s\n", user, realm);
00277 add_password(user, realm, tfp);
00278 }
00279 apr_file_close(f);
00280
00281
00282
00283 if (apr_file_copy(dirname, argv[1], APR_FILE_SOURCE_PERMS, cntxt) !=
00284 APR_SUCCESS) {
00285 apr_file_printf(errfile, "%s: unable to update file %s\n",
00286 argv[0], argv[1]);
00287 }
00288 apr_file_close(tfp);
00289
00290 return 0;
00291 }