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

« back to all changes in this revision

Viewing changes to srclib/apr/passwd/apr_getpass.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
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
/* apr_password_get.c: abstraction to provide for obtaining a password from the
 
18
 * command line in whatever way the OS supports.  In the best case, it's a
 
19
 * wrapper for the system library's getpass() routine; otherwise, we
 
20
 * use one we define ourselves.
 
21
 */
 
22
#include "apr_private.h"
 
23
#include "apr_strings.h"
 
24
#include "apr_lib.h"
 
25
#include "apr_errno.h"
 
26
#if APR_HAVE_SYS_TYPES_H
 
27
#include <sys/types.h>
 
28
#endif
 
29
#if APR_HAVE_ERRNO_H
 
30
#include <errno.h>
 
31
#endif
 
32
 
 
33
#if APR_HAVE_UNISTD_H
 
34
#include <unistd.h>
 
35
#endif
 
36
#if APR_HAVE_CONIO_H
 
37
#pragma warning(disable: 4032)
 
38
#include <conio.h>
 
39
#pragma warning(default: 4032)
 
40
#endif
 
41
#if APR_HAVE_STDLIB_H
 
42
#include <stdlib.h>
 
43
#endif
 
44
#if APR_HAVE_STRING_H
 
45
#include <string.h>
 
46
#endif
 
47
#if APR_HAVE_STRINGS_H
 
48
#include <strings.h>
 
49
#endif
 
50
 
 
51
#if defined(HAVE_TERMIOS_H) && !defined(HAVE_GETPASS)
 
52
#include <termios.h>
 
53
#endif
 
54
 
 
55
#if !APR_CHARSET_EBCDIC
 
56
#define LF 10
 
57
#define CR 13
 
58
#else /* APR_CHARSET_EBCDIC */
 
59
#define LF '\n'
 
60
#define CR '\r'
 
61
#endif /* APR_CHARSET_EBCDIC */
 
62
 
 
63
#define MAX_STRING_LEN 256
 
64
 
 
65
#define ERR_OVERFLOW 5
 
66
 
 
67
#ifndef HAVE_GETPASS
 
68
 
 
69
/* MPE, Win32, NetWare and BeOS all lack a native getpass() */
 
70
 
 
71
#if !defined(HAVE_TERMIOS_H) && !defined(WIN32) && !defined(NETWARE)
 
72
/*
 
73
 * MPE lacks getpass() and a way to suppress stdin echo.  So for now, just
 
74
 * issue the prompt and read the results with echo.  (Ugh).
 
75
 */
 
76
 
 
77
static char *getpass(const char *prompt)
 
78
{
 
79
    static char password[MAX_STRING_LEN];
 
80
 
 
81
    fputs(prompt, stderr);
 
82
    fgets((char *) &password, sizeof(password), stdin);
 
83
 
 
84
    return (char *) &password;
 
85
}
 
86
 
 
87
#elif defined (HAVE_TERMIOS_H)
 
88
#include <stdio.h>
 
89
 
 
90
static char *getpass(const char *prompt)
 
91
{
 
92
    struct termios attr;
 
93
    static char password[MAX_STRING_LEN];
 
94
    int n=0;
 
95
    fputs(prompt, stderr);
 
96
    fflush(stderr);
 
97
        
 
98
    if (tcgetattr(STDIN_FILENO, &attr) != 0)
 
99
        return NULL;
 
100
    attr.c_lflag &= ~(ECHO);
 
101
 
 
102
    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0)
 
103
            return NULL;
 
104
    while ((password[n] = getchar()) != '\n') {
 
105
        if (n < sizeof(password) - 1 && password[n] >= ' ' && password[n] <= '~') {
 
106
            n++;
 
107
        } else {
 
108
            fprintf(stderr,"\n");
 
109
            fputs(prompt, stderr);
 
110
            fflush(stderr);
 
111
            n = 0;
 
112
        }
 
113
    }
 
114
 
 
115
    password[n] = '\0';
 
116
    printf("\n");
 
117
    if (n > (MAX_STRING_LEN - 1)) {
 
118
        password[MAX_STRING_LEN - 1] = '\0';
 
119
    }
 
120
 
 
121
    attr.c_lflag |= ECHO;
 
122
    tcsetattr(STDIN_FILENO, TCSANOW, &attr);
 
123
    return (char*) &password;
 
124
}
 
125
 
 
126
#else
 
127
 
 
128
/*
 
129
 * Windows lacks getpass().  So we'll re-implement it here.
 
130
 */
 
131
 
 
132
static char *getpass(const char *prompt)
 
133
{
 
134
/* WCE lacks console. So the getpass is unsuported
 
135
 * The only way is to use the GUI so the getpass should be implemented
 
136
 * on per-application basis.
 
137
 */ 
 
138
#ifdef _WIN32_WCE
 
139
    return NULL;
 
140
#else
 
141
    static char password[128];
 
142
    int n = 0;
 
143
    int ch;
 
144
 
 
145
    fputs(prompt, stderr);
 
146
    
 
147
    while ((ch = _getch()) != '\r') {
 
148
        if (ch == EOF) /* EOF */ {
 
149
            fputs("[EOF]\n", stderr);
 
150
            return NULL;
 
151
        }
 
152
        else if (ch == 0 || ch == 0xE0) {
 
153
            /* FN Keys (0 or E0) are a sentinal for a FN code */ 
 
154
            ch = (ch << 4) | _getch();
 
155
            /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */
 
156
            if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) {
 
157
                password[--n] = '\0';
 
158
                fputs("\b \b", stderr);
 
159
            }
 
160
            else {
 
161
                fputc('\a', stderr);
 
162
            }
 
163
        }
 
164
        else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ {
 
165
            password[--n] = '\0';
 
166
            fputs("\b \b", stderr);
 
167
        }
 
168
        else if (ch == 3) /* CTRL+C */ {
 
169
            /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */
 
170
            fputs("^C\n", stderr);
 
171
            exit(-1);
 
172
        }
 
173
        else if (ch == 26) /* CTRL+Z */ {
 
174
            fputs("^Z\n", stderr);
 
175
            return NULL;
 
176
        }
 
177
        else if (ch == 27) /* ESC */ {
 
178
            fputc('\n', stderr);
 
179
            fputs(prompt, stderr);
 
180
            n = 0;
 
181
        }
 
182
        else if ((n < sizeof(password) - 1) && !apr_iscntrl(ch)) {
 
183
            password[n++] = ch;
 
184
            fputc('*', stderr);
 
185
        }
 
186
        else {
 
187
            fputc('\a', stderr);
 
188
        }
 
189
    }
 
190
 
 
191
    fputc('\n', stderr);
 
192
    password[n] = '\0';
 
193
    return password;
 
194
#endif
 
195
}
 
196
 
 
197
#endif /* no getchar or _getch */
 
198
 
 
199
#endif /* no getpass */
 
200
 
 
201
/*
 
202
 * Use the OS getpass() routine (or our own) to obtain a password from
 
203
 * the input stream.
 
204
 *
 
205
 * Exit values:
 
206
 *  0: Success
 
207
 *  5: Partial success; entered text truncated to the size of the
 
208
 *     destination buffer
 
209
 *
 
210
 * Restrictions: Truncation also occurs according to the host system's
 
211
 * getpass() semantics, or at position 255 if our own version is used,
 
212
 * but the caller is *not* made aware of it unless their own buffer is
 
213
 * smaller than our own.
 
214
 */
 
215
 
 
216
APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, apr_size_t *bufsiz)
 
217
{
 
218
#ifdef HAVE_GETPASSPHRASE
 
219
    char *pw_got = getpassphrase(prompt);
 
220
#else
 
221
    char *pw_got = getpass(prompt);
 
222
#endif
 
223
    apr_status_t rv = APR_SUCCESS;
 
224
 
 
225
    if (!pw_got)
 
226
        return APR_EINVAL;
 
227
    if (strlen(pw_got) >= *bufsiz) {
 
228
        rv = APR_ENAMETOOLONG;
 
229
    }
 
230
    apr_cpystrn(pwbuf, pw_got, *bufsiz);
 
231
    memset(pw_got, 0, strlen(pw_got));
 
232
    return rv;
 
233
}