1/* 2 * Copyright (c) 2011-12 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Copyright (c) 1997 - 2000, 2005 Kungliga Tekniska Högskolan 26 * (Royal Institute of Technology, Stockholm, Sweden). 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 40 * 3. Neither the name of the Institute nor the names of its contributors 41 * may be used to endorse or promote products derived from this software 42 * without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57#include "ossl-config.h" 58 59#include <fcntl.h> 60#include <stdio.h> 61#include <stdlib.h> 62#include <string.h> 63#include <signal.h> 64#ifdef HAVE_TERMIOS_H 65#include <termios.h> 66#endif 67 68#include "ossl-ui.h" 69 70#ifdef HAVE_CONIO_H 71#include <conio.h> 72#endif 73 74static sig_atomic_t intr_flag; 75 76static void 77intr(int sig) 78{ 79 intr_flag++; 80} 81 82 83#ifdef HAVE_CONIO_H 84 85/* 86 * Windows does console slightly different then then unix case. 87 */ 88static int 89read_string(const char *preprompt, const char *prompt, 90 char *buf, size_t len, int echo) 91{ 92 int of = 0; 93 int c; 94 char *p; 95 96 void (*oldsigintr)(int); 97 98 _cprintf("%s%s", preprompt, prompt); 99 100 oldsigintr = signal(SIGINT, intr); 101 102 p = buf; 103 while (intr_flag == 0) { 104 c = ((echo) ? _getche() : _getch()); 105 if ((c == '\n') || (c == '\r')) { 106 break; 107 } 108 if (of == 0) { 109 *p++ = c; 110 } 111 of = (p == buf + len); 112 } 113 if (of) { 114 p--; 115 } 116 *p = 0; 117 118 if (echo == 0) { 119 printf("\n"); 120 } 121 122 signal(SIGINT, oldsigintr); 123 124 if (intr_flag) { 125 return (-2); 126 } 127 if (of) { 128 return (-1); 129 } 130 return (0); 131} 132 133 134#else /* !HAVE_CONIO_H */ 135 136#ifndef NSIG 137#define NSIG 47 138#endif 139 140#define FLAG_ECHO 1 141#define FLAG_USE_STDIO 2 142 143 144static int 145read_string(const char *preprompt, const char *prompt, 146 char *buf, size_t len, int flags) 147{ 148 struct sigaction sigs[NSIG]; 149 int oksigs[NSIG]; 150 struct sigaction sa; 151 FILE *tty; 152 int ret = 0; 153 int of = 0; 154 int i; 155 int c; 156 char *p; 157 158 struct termios t_new, t_old; 159 160 memset(&oksigs, 0, sizeof(oksigs)); 161 162 memset(&sa, 0, sizeof(sa)); 163 sa.sa_handler = intr; 164 sigemptyset(&sa.sa_mask); 165 sa.sa_flags = 0; 166 for (i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) { 167 if (i != SIGALRM) { 168 if (sigaction(i, &sa, &sigs[i]) == 0) { 169 oksigs[i] = 1; 170 } 171 } 172 } 173 174 /* 175 * Don't use /dev/tty for now since server tools want to to 176 * read/write from stdio when setting up and interacting with the 177 * Kerberos subsystem. 178 * 179 * When <rdar://problem/7308846> is in we can remove this, this is 180 * to make transiation easier for server folks. 181 */ 182 if ((flags & FLAG_USE_STDIO) != 0) { 183 tty = stdin; 184 } else if ((tty = fopen("/dev/tty", "r")) != NULL) { 185 int flg, fd = fileno(tty); 186 /* rk_cloexec_file(tty); */ 187 if ((flg = fcntl(fd, F_GETFD)) != -1) { 188 fcntl(fd, F_SETFD, flg | FD_CLOEXEC); 189 } 190 } else{ 191 tty = stdin; 192 } 193 194 fprintf(stderr, "%s%s", preprompt, prompt); 195 fflush(stderr); 196 197 if ((flags & FLAG_ECHO) == 0) { 198 tcgetattr(fileno(tty), &t_old); 199 memcpy(&t_new, &t_old, sizeof(t_new)); 200 t_new.c_lflag &= ~ECHO; 201 tcsetattr(fileno(tty), TCSANOW, &t_new); 202 } 203 intr_flag = 0; 204 p = buf; 205 while (intr_flag == 0) { 206 c = getc(tty); 207 if (c == EOF) { 208 if (!ferror(tty)) { 209 ret = 1; 210 } 211 break; 212 } 213 if (c == '\n') { 214 break; 215 } 216 if (of == 0) { 217 *p++ = c; 218 } 219 of = (p == buf + len); 220 } 221 if (of) { 222 p--; 223 } 224 *p = 0; 225 226 if ((flags & FLAG_ECHO) == 0) { 227 fprintf(stderr, "\n"); 228 tcsetattr(fileno(tty), TCSANOW, &t_old); 229 } 230 231 if (tty != stdin) { 232 fclose(tty); 233 } 234 235 for (i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) { 236 if (oksigs[i]) { 237 sigaction(i, &sigs[i], NULL); 238 } 239 } 240 241 if (ret) { 242 return (-3); 243 } 244 if (intr_flag) { 245 return (-2); 246 } 247 if (of) { 248 return (-1); 249 } 250 return (0); 251} 252 253 254#endif /* HAVE_CONIO_H */ 255 256int 257UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify) 258{ 259 int ret; 260 261 ret = read_string("", prompt, buf, length, 0); 262 if (ret) { 263 return (ret); 264 } 265 266 if (verify) { 267 char *buf2; 268 buf2 = malloc(length); 269 if (buf2 == NULL) { 270 return (1); 271 } 272 273 ret = read_string("Verify password - ", prompt, buf2, length, 0); 274 if (ret) { 275 free(buf2); 276 return (ret); 277 } 278 if (strcmp(buf2, buf) != 0) { 279 ret = 1; 280 } 281 memset(buf2, 0, length); 282 free(buf2); 283 } 284 return (ret); 285} 286 287 288int 289UI_UTIL_read_pw_string_stdio(char *buf, int length, const char *prompt, int verify) 290{ 291 int ret; 292 293 ret = read_string("", prompt, buf, length, FLAG_USE_STDIO); 294 if (ret) { 295 return (ret); 296 } 297 298 if (verify) { 299 char *buf2; 300 buf2 = malloc(length); 301 if (buf2 == NULL) { 302 return (1); 303 } 304 305 ret = read_string("Verify password - ", prompt, buf2, length, FLAG_USE_STDIO); 306 if (ret) { 307 free(buf2); 308 return (ret); 309 } 310 if (strcmp(buf2, buf) != 0) { 311 ret = 1; 312 } 313 memset(buf2, 0, length); 314 free(buf2); 315 } 316 return (ret); 317} 318