~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to support/htdigest.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/******************************************************************************
 
18
 ******************************************************************************
 
19
 * NOTE! This program is not safe as a setuid executable!  Do not make it
 
20
 * setuid!
 
21
 ******************************************************************************
 
22
 *****************************************************************************/
 
23
/*
 
24
 * htdigest.c: simple program for manipulating digest passwd file for Apache
 
25
 *
 
26
 * by Alexei Kosut, based on htpasswd.c, by Rob McCool
 
27
 */
 
28
 
 
29
#include "apr.h"
 
30
#include "apr_file_io.h"
 
31
#include "apr_md5.h"
 
32
#include "apr_lib.h"            /* for apr_getpass() */
 
33
#include "apr_general.h"
 
34
#include "apr_signal.h"
 
35
#include "apr_strings.h"        /* for apr_pstrdup() */
 
36
 
 
37
#define APR_WANT_STDIO
 
38
#define APR_WANT_STRFUNC
 
39
#include "apr_want.h"
 
40
 
 
41
#if APR_HAVE_SYS_TYPES_H
 
42
#include <sys/types.h>
 
43
#endif
 
44
#if APR_HAVE_STDLIB_H
 
45
#include <stdlib.h>
 
46
#endif
 
47
 
 
48
#ifdef WIN32
 
49
#include <conio.h>
 
50
#endif
 
51
 
 
52
 
 
53
#if APR_CHARSET_EBCDIC
 
54
#define LF '\n'
 
55
#define CR '\r'
 
56
#else
 
57
#define LF 10
 
58
#define CR 13
 
59
#endif /* APR_CHARSET_EBCDIC */
 
60
 
 
61
#define MAX_STRING_LEN 256
 
62
 
 
63
apr_file_t *tfp = NULL;
 
64
apr_file_t *errfile;
 
65
apr_pool_t *cntxt;
 
66
#if APR_CHARSET_EBCDIC
 
67
apr_xlate_t *to_ascii;
 
68
#endif
 
69
 
 
70
static void cleanup_tempfile_and_exit(int rc)
 
71
{
 
72
    if (tfp) {
 
73
        apr_file_close(tfp);
 
74
    }
 
75
    exit(rc);
 
76
}
 
77
 
 
78
static void getword(char *word, char *line, char stop)
 
79
{
 
80
    int x = 0, y;
 
81
 
 
82
    for (x = 0; ((line[x]) && (line[x] != stop)); x++)
 
83
        word[x] = line[x];
 
84
 
 
85
    word[x] = '\0';
 
86
    if (line[x])
 
87
        ++x;
 
88
    y = 0;
 
89
 
 
90
    while ((line[y++] = line[x++]));
 
91
}
 
92
 
 
93
static int get_line(char *s, int n, apr_file_t *f)
 
94
{
 
95
    register int i = 0;
 
96
    char ch;
 
97
    apr_status_t rv = APR_EINVAL;
 
98
 
 
99
    while (i < (n - 1) &&
 
100
           ((rv = apr_file_getc(&ch, f)) == APR_SUCCESS) && (ch != '\n')) {
 
101
        s[i++] = ch;
 
102
    }
 
103
    if (ch == '\n')
 
104
        s[i++] = ch;
 
105
    s[i] = '\0';
 
106
 
 
107
    if (rv != APR_SUCCESS)
 
108
        return 1;
 
109
 
 
110
    return 0;
 
111
}
 
112
 
 
113
static void putline(apr_file_t *f, char *l)
 
114
{
 
115
    int x;
 
116
 
 
117
    for (x = 0; l[x]; x++)
 
118
        apr_file_putc(l[x], f);
 
119
}
 
120
 
 
121
 
 
122
static void add_password(const char *user, const char *realm, apr_file_t *f)
 
123
{
 
124
    char *pw;
 
125
    apr_md5_ctx_t context;
 
126
    unsigned char digest[16];
 
127
    char string[MAX_STRING_LEN];
 
128
    char pwin[MAX_STRING_LEN];
 
129
    char pwv[MAX_STRING_LEN];
 
130
    unsigned int i;
 
131
    apr_size_t len = sizeof(pwin);
 
132
 
 
133
    if (apr_password_get("New password: ", pwin, &len) != APR_SUCCESS) {
 
134
        apr_file_printf(errfile, "password too long");
 
135
        cleanup_tempfile_and_exit(5);
 
136
    }
 
137
    len = sizeof(pwin);
 
138
    apr_password_get("Re-type new password: ", pwv, &len);
 
139
    if (strcmp(pwin, pwv) != 0) {
 
140
        apr_file_printf(errfile, "They don't match, sorry.\n");
 
141
        cleanup_tempfile_and_exit(1);
 
142
    }
 
143
    pw = pwin;
 
144
    apr_file_printf(f, "%s:%s:", user, realm);
 
145
 
 
146
    /* Do MD5 stuff */
 
147
    sprintf(string, "%s:%s:%s", user, realm, pw);
 
148
 
 
149
    apr_md5_init(&context);
 
150
#if APR_CHARSET_EBCDIC
 
151
    apr_md5_set_xlate(&context, to_ascii);
 
152
#endif
 
153
    apr_md5_update(&context, (unsigned char *) string, strlen(string));
 
154
    apr_md5_final(digest, &context);
 
155
 
 
156
    for (i = 0; i < 16; i++)
 
157
        apr_file_printf(f, "%02x", digest[i]);
 
158
 
 
159
    apr_file_printf(f, "\n");
 
160
}
 
161
 
 
162
static void usage(void)
 
163
{
 
164
    apr_file_printf(errfile, "Usage: htdigest [-c] passwordfile realm username\n");
 
165
    apr_file_printf(errfile, "The -c flag creates a new file.\n");
 
166
    exit(1);
 
167
}
 
168
 
 
169
static void interrupted(void)
 
170
{
 
171
    apr_file_printf(errfile, "Interrupted.\n");
 
172
    cleanup_tempfile_and_exit(1);
 
173
}
 
174
 
 
175
static void terminate(void)
 
176
{
 
177
    apr_terminate();
 
178
#ifdef NETWARE
 
179
    pressanykey();
 
180
#endif
 
181
}
 
182
 
 
183
int main(int argc, const char * const argv[])
 
184
{
 
185
    apr_file_t *f;
 
186
    apr_status_t rv;
 
187
    char tn[] = "htdigest.tmp.XXXXXX";
 
188
    char *dirname;
 
189
    char user[MAX_STRING_LEN];
 
190
    char realm[MAX_STRING_LEN];
 
191
    char line[MAX_STRING_LEN];
 
192
    char l[MAX_STRING_LEN];
 
193
    char w[MAX_STRING_LEN];
 
194
    char x[MAX_STRING_LEN];
 
195
    int found;
 
196
 
 
197
    apr_app_initialize(&argc, &argv, NULL);
 
198
    atexit(terminate);
 
199
    apr_pool_create(&cntxt, NULL);
 
200
    apr_file_open_stderr(&errfile, cntxt);
 
201
 
 
202
#if APR_CHARSET_EBCDIC
 
203
    rv = apr_xlate_open(&to_ascii, "ISO-8859-1", APR_DEFAULT_CHARSET, cntxt);
 
204
    if (rv) {
 
205
        apr_file_printf(errfile, "apr_xlate_open(): %s (%d)\n",
 
206
                apr_strerror(rv, line, sizeof(line)), rv);
 
207
        exit(1);
 
208
    }
 
209
#endif
 
210
 
 
211
    apr_signal(SIGINT, (void (*)(int)) interrupted);
 
212
    if (argc == 5) {
 
213
        if (strcmp(argv[1], "-c"))
 
214
            usage();
 
215
        rv = apr_file_open(&f, argv[2], APR_WRITE | APR_CREATE,
 
216
                           APR_OS_DEFAULT, cntxt);
 
217
        if (rv != APR_SUCCESS) {
 
218
            char errmsg[120];
 
219
 
 
220
            apr_file_printf(errfile, "Could not open passwd file %s for writing: %s\n",
 
221
                    argv[2],
 
222
                    apr_strerror(rv, errmsg, sizeof errmsg));
 
223
            exit(1);
 
224
        }
 
225
        apr_file_printf(errfile, "Adding password for %s in realm %s.\n",
 
226
                    argv[4], argv[3]);
 
227
        add_password(argv[4], argv[3], f);
 
228
        apr_file_close(f);
 
229
        exit(0);
 
230
    }
 
231
    else if (argc != 4)
 
232
        usage();
 
233
 
 
234
    if (apr_temp_dir_get((const char**)&dirname, cntxt) != APR_SUCCESS) {
 
235
        apr_file_printf(errfile, "%s: could not determine temp dir\n",
 
236
                        argv[0]);
 
237
        exit(1);
 
238
    }
 
239
    dirname = apr_psprintf(cntxt, "%s/%s", dirname, tn);
 
240
 
 
241
    if (apr_file_mktemp(&tfp, dirname, 0, cntxt) != APR_SUCCESS) {
 
242
        apr_file_printf(errfile, "Could not open temp file %s.\n", dirname);
 
243
        exit(1);
 
244
    }
 
245
 
 
246
    if (apr_file_open(&f, argv[1], APR_READ, APR_OS_DEFAULT, cntxt) != APR_SUCCESS) {
 
247
        apr_file_printf(errfile,
 
248
                "Could not open passwd file %s for reading.\n", argv[1]);
 
249
        apr_file_printf(errfile, "Use -c option to create new one.\n");
 
250
        cleanup_tempfile_and_exit(1);
 
251
    }
 
252
    apr_cpystrn(user, argv[3], sizeof(user));
 
253
    apr_cpystrn(realm, argv[2], sizeof(realm));
 
254
 
 
255
    found = 0;
 
256
    while (!(get_line(line, MAX_STRING_LEN, f))) {
 
257
        if (found || (line[0] == '#') || (!line[0])) {
 
258
            putline(tfp, line);
 
259
            continue;
 
260
        }
 
261
        strcpy(l, line);
 
262
        getword(w, l, ':');
 
263
        getword(x, l, ':');
 
264
        if (strcmp(user, w) || strcmp(realm, x)) {
 
265
            putline(tfp, line);
 
266
            continue;
 
267
        }
 
268
        else {
 
269
            apr_file_printf(errfile, "Changing password for user %s in realm %s\n",
 
270
                    user, realm);
 
271
            add_password(user, realm, tfp);
 
272
            found = 1;
 
273
        }
 
274
    }
 
275
    if (!found) {
 
276
        apr_file_printf(errfile, "Adding user %s in realm %s\n", user, realm);
 
277
        add_password(user, realm, tfp);
 
278
    }
 
279
    apr_file_close(f);
 
280
 
 
281
    /* The temporary file has all the data, just copy it to the new location.
 
282
     */
 
283
    if (apr_file_copy(dirname, argv[1], APR_FILE_SOURCE_PERMS, cntxt) !=
 
284
                APR_SUCCESS) {
 
285
        apr_file_printf(errfile, "%s: unable to update file %s\n",
 
286
                        argv[0], argv[1]);
 
287
    }
 
288
    apr_file_close(tfp);
 
289
 
 
290
    return 0;
 
291
}