upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / support / htdigest.c
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, "ISO8859-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 }