s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / third_party / heimdal / lib / hcrypto / ui.c
1 /*
2  * Copyright (c) 1997 - 2000, 2005 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include <config.h>
35 #include <roken.h>
36 #include <signal.h>
37 #ifdef HAVE_TERMIOS_H
38 #include <termios.h>
39 #endif
40
41 #include <ui.h>
42 #ifdef HAVE_CONIO_H
43 #include <conio.h>
44 #endif
45
46 static sig_atomic_t intr_flag;
47
48 static void
49 intr(int sig)
50 {
51     intr_flag++;
52 }
53
54 #ifdef HAVE_CONIO_H
55
56 /*
57  * Windows does console slightly different then then unix case.
58  */
59
60 static int
61 read_string(const char *preprompt, const char *prompt,
62             char *buf, size_t len, int echo)
63 {
64     int of = 0;
65     int c;
66     char *p;
67     void (*oldsigintr)(int);
68
69     _cprintf("%s%s", preprompt, prompt);
70
71     oldsigintr = signal(SIGINT, intr);
72
73     p = buf;
74     while(intr_flag == 0){
75         c = ((echo)? _getche(): _getch());
76         if(c == '\n' || c == '\r')
77             break;
78         if(of == 0)
79             *p++ = c;
80         of = (p == buf + len);
81     }
82     if(of)
83         p--;
84     *p = 0;
85
86     if(echo == 0){
87         printf("\n");
88     }
89
90     signal(SIGINT, oldsigintr);
91
92     if(intr_flag)
93         return -2;
94     if(of)
95         return -1;
96     return 0;
97 }
98
99 #else /* !HAVE_CONIO_H */
100
101 #ifndef NSIG
102 #define NSIG 47
103 #endif
104
105 static int
106 read_string(const char *preprompt, const char *prompt,
107             char *buf, size_t len, int echo)
108 {
109     struct sigaction sigs[NSIG];
110     int oksigs[NSIG];
111     struct sigaction sa;
112     FILE *tty;
113     int ret = 0;
114     int of = 0;
115     int i;
116     int c;
117     char *p;
118
119     struct termios t_new, t_old;
120
121     memset(&oksigs, 0, sizeof(oksigs));
122
123     memset(&sa, 0, sizeof(sa));
124     sa.sa_handler = intr;
125     sigemptyset(&sa.sa_mask);
126     sa.sa_flags = 0;
127     for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++)
128         if (i != SIGALRM)
129             if (sigaction(i, &sa, &sigs[i]) == 0)
130                 oksigs[i] = 1;
131
132     if((tty = fopen("/dev/tty", "r")) != NULL)
133         rk_cloexec_file(tty);
134     else
135         tty = stdin;
136
137     fprintf(stderr, "%s%s", preprompt, prompt);
138     fflush(stderr);
139
140     if(echo == 0){
141         tcgetattr(fileno(tty), &t_old);
142         memcpy(&t_new, &t_old, sizeof(t_new));
143         t_new.c_lflag &= ~ECHO;
144         tcsetattr(fileno(tty), TCSANOW, &t_new);
145     }
146     intr_flag = 0;
147     p = buf;
148     while(intr_flag == 0){
149         c = getc(tty);
150         if(c == EOF){
151             if(!ferror(tty))
152                 ret = 1;
153             break;
154         }
155         if(c == '\n')
156             break;
157         if(of == 0)
158             *p++ = c;
159         of = (p == buf + len);
160     }
161     if(of)
162         p--;
163     *p = 0;
164
165     if(echo == 0){
166         fprintf(stderr, "\n");
167         tcsetattr(fileno(tty), TCSANOW, &t_old);
168     }
169
170     if(tty != stdin)
171         fclose(tty);
172
173     for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++)
174         if (oksigs[i])
175             sigaction(i, &sigs[i], NULL);
176
177     if(ret)
178         return -3;
179     if(intr_flag)
180         return -2;
181     if(of)
182         return -1;
183     return 0;
184 }
185
186 #endif /* HAVE_CONIO_H */
187
188 int
189 UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify)
190 {
191     int ret;
192
193     ret = read_string("", prompt, buf, length, 0);
194     if (ret)
195         return ret;
196
197     if (verify & UI_UTIL_FLAG_VERIFY) {
198         char *buf2;
199         buf2 = malloc(length);
200         if (buf2 == NULL)
201             return 1;
202
203         ret = read_string("Verify password - ", prompt, buf2, length, 0);
204         if (ret) {
205             free(buf2);
206             return ret;
207         }
208         if (strcmp(buf2, buf) != 0) {
209             if (!(verify & UI_UTIL_FLAG_VERIFY_SILENT)) {
210                 fprintf(stderr, "Verify failure\n");
211                 fflush(stderr);
212             }
213             ret = 1;
214         }
215         free(buf2);
216     }
217     return ret;
218 }