get_password.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. Copyright (c) 2012-2020 Roger Light <roger@atchoo.org>
  3. All rights reserved. This program and the accompanying materials
  4. are made available under the terms of the Eclipse Public License 2.0
  5. and Eclipse Distribution License v1.0 which accompany this distribution.
  6. The Eclipse Public License is available at
  7. https://www.eclipse.org/legal/epl-2.0/
  8. and the Eclipse Distribution License is available at
  9. http://www.eclipse.org/org/documents/edl-v10.php.
  10. SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
  11. Contributors:
  12. Roger Light - initial implementation and documentation.
  13. */
  14. #include "config.h"
  15. #include <stdbool.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #ifdef WIN32
  20. # include <windows.h>
  21. # include <process.h>
  22. # define snprintf sprintf_s
  23. # include <io.h>
  24. # include <windows.h>
  25. #else
  26. # include <unistd.h>
  27. # include <termios.h>
  28. # include <sys/stat.h>
  29. #endif
  30. #include "get_password.h"
  31. #define MAX_BUFFER_LEN 65500
  32. #define SALT_LEN 12
  33. void get_password__reset_term(void)
  34. {
  35. #ifndef WIN32
  36. struct termios ts;
  37. tcgetattr(0, &ts);
  38. ts.c_lflag |= ECHO | ICANON;
  39. tcsetattr(0, TCSANOW, &ts);
  40. #endif
  41. }
  42. static int gets_quiet(char *s, int len)
  43. {
  44. #ifdef WIN32
  45. HANDLE h;
  46. DWORD con_orig, con_quiet = 0;
  47. DWORD read_len = 0;
  48. memset(s, 0, len);
  49. h = GetStdHandle(STD_INPUT_HANDLE);
  50. GetConsoleMode(h, &con_orig);
  51. con_quiet = con_orig;
  52. con_quiet &= ~ENABLE_ECHO_INPUT;
  53. con_quiet |= ENABLE_LINE_INPUT;
  54. SetConsoleMode(h, con_quiet);
  55. if(!ReadConsole(h, s, len, &read_len, NULL)){
  56. SetConsoleMode(h, con_orig);
  57. return 1;
  58. }
  59. while(s[strlen(s)-1] == 10 || s[strlen(s)-1] == 13){
  60. s[strlen(s)-1] = 0;
  61. }
  62. if(strlen(s) == 0){
  63. return 1;
  64. }
  65. SetConsoleMode(h, con_orig);
  66. return 0;
  67. #else
  68. struct termios ts_quiet, ts_orig;
  69. char *rs;
  70. memset(s, 0, (size_t)len);
  71. tcgetattr(0, &ts_orig);
  72. ts_quiet = ts_orig;
  73. ts_quiet.c_lflag &= (unsigned int)(~(ECHO | ICANON));
  74. tcsetattr(0, TCSANOW, &ts_quiet);
  75. rs = fgets(s, len, stdin);
  76. tcsetattr(0, TCSANOW, &ts_orig);
  77. if(!rs){
  78. return 1;
  79. }else{
  80. while(s[strlen(s)-1] == 10 || s[strlen(s)-1] == 13){
  81. s[strlen(s)-1] = 0;
  82. }
  83. if(strlen(s) == 0){
  84. return 1;
  85. }
  86. }
  87. return 0;
  88. #endif
  89. }
  90. int get_password(const char *prompt, const char *verify_prompt, bool quiet, char *password, size_t len)
  91. {
  92. char pw1[MAX_BUFFER_LEN], pw2[MAX_BUFFER_LEN];
  93. size_t minLen;
  94. minLen = len < MAX_BUFFER_LEN ? len : MAX_BUFFER_LEN;
  95. printf("%s", prompt);
  96. fflush(stdout);
  97. if(gets_quiet(pw1, (int)minLen)){
  98. if(!quiet){
  99. fprintf(stderr, "Error: Empty password.\n");
  100. }
  101. return 1;
  102. }
  103. printf("\n");
  104. if(verify_prompt){
  105. printf("%s", verify_prompt);
  106. fflush(stdout);
  107. if(gets_quiet(pw2, (int)minLen)){
  108. if(!quiet){
  109. fprintf(stderr, "Error: Empty password.\n");
  110. }
  111. return 1;
  112. }
  113. printf("\n");
  114. if(strcmp(pw1, pw2)){
  115. if(!quiet){
  116. fprintf(stderr, "Error: Passwords do not match.\n");
  117. }
  118. return 2;
  119. }
  120. }
  121. strncpy(password, pw1, minLen);
  122. return 0;
  123. }