s4:heimdal: import lorikeet-heimdal-200908052208 (commit 370a73a74199a5a55188340906e1...
[ira/wip.git] / source4 / 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
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <signal.h>
40 #include <termios.h>
41 #include <roken.h>
42
43 #include <ui.h>
44
45 static sig_atomic_t intr_flag;
46
47 static void
48 intr(int sig)
49 {
50     intr_flag++;
51 }
52
53 #ifndef NSIG
54 #define NSIG 47
55 #endif
56
57 static int
58 read_string(const char *preprompt, const char *prompt,
59             char *buf, size_t len, int echo)
60 {
61     struct sigaction sigs[NSIG];
62     int oksigs[NSIG];
63     struct sigaction sa;
64     FILE *tty;
65     int ret = 0;
66     int of = 0;
67     int i;
68     int c;
69     char *p;
70
71     struct termios t_new, t_old;
72
73     memset(&oksigs, 0, sizeof(oksigs));
74
75     memset(&sa, 0, sizeof(sa));
76     sa.sa_handler = intr;
77     sigemptyset(&sa.sa_mask);
78     sa.sa_flags = 0;
79     for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++)
80         if (i != SIGALRM)
81             if (sigaction(i, &sa, &sigs[i]) == 0)
82                 oksigs[i] = 1;
83
84     if((tty = fopen("/dev/tty", "r")) != NULL)
85         rk_cloexec_file(tty);
86     else
87         tty = stdin;
88
89     fprintf(stderr, "%s%s", preprompt, prompt);
90     fflush(stderr);
91
92     if(echo == 0){
93         tcgetattr(fileno(tty), &t_old);
94         memcpy(&t_new, &t_old, sizeof(t_new));
95         t_new.c_lflag &= ~ECHO;
96         tcsetattr(fileno(tty), TCSANOW, &t_new);
97     }
98     intr_flag = 0;
99     p = buf;
100     while(intr_flag == 0){
101         c = getc(tty);
102         if(c == EOF){
103             if(!ferror(tty))
104                 ret = 1;
105             break;
106         }
107         if(c == '\n')
108             break;
109         if(of == 0)
110             *p++ = c;
111         of = (p == buf + len);
112     }
113     if(of)
114         p--;
115     *p = 0;
116
117     if(echo == 0){
118         fprintf(stderr, "\n");
119         tcsetattr(fileno(tty), TCSANOW, &t_old);
120     }
121
122     if(tty != stdin)
123         fclose(tty);
124
125     for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++)
126         if (oksigs[i])
127             sigaction(i, &sigs[i], NULL);
128
129     if(ret)
130         return -3;
131     if(intr_flag)
132         return -2;
133     if(of)
134         return -1;
135     return 0;
136 }
137
138 int
139 UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify)
140 {
141     int ret;
142
143     ret = read_string("", prompt, buf, length, 0);
144     if (ret)
145         return ret;
146
147     if (verify) {
148         char *buf2;
149         buf2 = malloc(length);
150         if (buf2 == NULL)
151             return 1;
152
153         ret = read_string("Verify password - ", prompt, buf2, length, 0);
154         if (ret) {
155             free(buf2);
156             return ret;
157         }
158         if (strcmp(buf2, buf) != 0)
159             ret = 1;
160         free(buf2);
161     }
162     return ret;
163 }