diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:24:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:24:41 +0000 |
commit | a9bcc81f821d7c66f623779fa5147e728eb3c388 (patch) | |
tree | 98676963bcdd537ae5908a067a8eb110b93486a6 /libfreerdp/utils/passphrase.c | |
parent | Initial commit. (diff) | |
download | freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.tar.xz freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.zip |
Adding upstream version 3.3.0+dfsg1.upstream/3.3.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | libfreerdp/utils/passphrase.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/libfreerdp/utils/passphrase.c b/libfreerdp/utils/passphrase.c new file mode 100644 index 0000000..016da79 --- /dev/null +++ b/libfreerdp/utils/passphrase.c @@ -0,0 +1,299 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Passphrase Handling Utils + * + * Copyright 2011 Shea Levy <shea@shealevy.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <freerdp/config.h> +#include <freerdp/freerdp.h> + +#include <errno.h> +#include <freerdp/utils/passphrase.h> + +#ifdef _WIN32 + +#include <stdio.h> +#include <io.h> +#include <conio.h> +#include <wincred.h> + +static char read_chr(FILE* f) +{ + char chr; + const BOOL isTty = _isatty(_fileno(f)); + if (isTty) + return fgetc(f); + if (fscanf_s(f, "%c", &chr, (UINT32)sizeof(char)) && !feof(f)) + return chr; + return 0; +} + +int freerdp_interruptible_getc(rdpContext* context, FILE* f) +{ + return read_chr(f); +} + +char* freerdp_passphrase_read(rdpContext* context, const char* prompt, char* buf, size_t bufsiz, + int from_stdin) +{ + WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 'p', 'r', 'e', 'f', 'i', + 'l', 'l', 'e', 'd', '\0' }; + WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 }; + BOOL fSave = FALSE; + DWORD dwFlags = 0; + WCHAR* promptW = ConvertUtf8ToWCharAlloc(prompt, NULL); + const DWORD status = + CredUICmdLinePromptForCredentialsW(promptW, NULL, 0, UserNameW, ARRAYSIZE(UserNameW), + PasswordW, ARRAYSIZE(PasswordW), &fSave, dwFlags); + free(promptW); + if (ConvertWCharNToUtf8(PasswordW, ARRAYSIZE(PasswordW), buf, bufsiz) < 0) + return NULL; + return buf; +} + +#elif !defined(ANDROID) + +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <termios.h> +#include <unistd.h> +#include <freerdp/utils/signal.h> + +#if defined(WINPR_HAVE_POLL_H) && !defined(__APPLE__) +#include <poll.h> +#else +#include <time.h> +#include <sys/select.h> +#endif + +static int wait_for_fd(int fd, int timeout) +{ + int status = 0; +#if defined(WINPR_HAVE_POLL_H) && !defined(__APPLE__) + struct pollfd pollset = { 0 }; + pollset.fd = fd; + pollset.events = POLLIN; + pollset.revents = 0; + + do + { + status = poll(&pollset, 1, timeout); + } while ((status < 0) && (errno == EINTR)); + +#else + fd_set rset = { 0 }; + struct timeval tv = { 0 }; + FD_ZERO(&rset); + FD_SET(fd, &rset); + + if (timeout) + { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + } + + do + { + status = select(fd + 1, &rset, NULL, NULL, timeout ? &tv : NULL); + } while ((status < 0) && (errno == EINTR)); + +#endif + return status; +} + +static void replace_char(char* buffer, size_t buffer_len, const char* toreplace) +{ + while (*toreplace != '\0') + { + char* ptr = NULL; + while ((ptr = strrchr(buffer, *toreplace)) != NULL) + *ptr = '\0'; + toreplace++; + } +} + +char* freerdp_passphrase_read(rdpContext* context, const char* prompt, char* buf, size_t bufsiz, + int from_stdin) +{ + BOOL terminal_needs_reset = FALSE; + char term_name[L_ctermid] = { 0 }; + int term_file = 0; + + FILE* fout = NULL; + + if (bufsiz == 0) + { + errno = EINVAL; + return NULL; + } + + ctermid(term_name); + int terminal_fildes = 0; + if (from_stdin || strcmp(term_name, "") == 0 || (term_file = open(term_name, O_RDWR)) == -1) + { + fout = stdout; + terminal_fildes = STDIN_FILENO; + } + else + { + fout = fdopen(term_file, "w"); + terminal_fildes = term_file; + } + + struct termios orig_flags = { 0 }; + if (tcgetattr(terminal_fildes, &orig_flags) != -1) + { + struct termios new_flags = { 0 }; + new_flags = orig_flags; + new_flags.c_lflag &= ~ECHO; + new_flags.c_lflag |= ECHONL; + terminal_needs_reset = TRUE; + if (tcsetattr(terminal_fildes, TCSAFLUSH, &new_flags) == -1) + terminal_needs_reset = FALSE; + } + + FILE* fp = fdopen(terminal_fildes, "r"); + if (!fp) + goto error; + + fprintf(fout, "%s", prompt); + fflush(fout); + + char* ptr = NULL; + size_t ptr_len = 0; + + const SSIZE_T res = freerdp_interruptible_get_line(context, &ptr, &ptr_len, fp); + if (res < 0) + goto error; + replace_char(ptr, ptr_len, "\r\n"); + + strncpy(buf, ptr, MIN(bufsiz, ptr_len)); + free(ptr); + if (terminal_needs_reset) + { + if (tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags) == -1) + goto error; + } + + if (terminal_fildes != STDIN_FILENO) + { + if (fclose(fp) == -1) + goto error; + } + + return buf; + +error: +{ + int saved_errno = errno; + if (terminal_needs_reset) + tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags); + if (terminal_fildes != STDIN_FILENO) + { + if (fp) + fclose(fp); + } + errno = saved_errno; + return NULL; +} +} + +int freerdp_interruptible_getc(rdpContext* context, FILE* f) +{ + int rc = EOF; + const int fd = fileno(f); + + const int orig = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, orig | O_NONBLOCK); + do + { + const int res = wait_for_fd(fd, 10); + if (res != 0) + { + char c = 0; + const ssize_t rd = read(fd, &c, 1); + if (rd == 1) + rc = c; + break; + } + } while (!freerdp_shall_disconnect_context(context)); + + fcntl(fd, F_SETFL, orig); + return rc; +} + +#else + +char* freerdp_passphrase_read(rdpContext* context, const char* prompt, char* buf, size_t bufsiz, + int from_stdin) +{ + return NULL; +} + +int freerdp_interruptible_getc(rdpContext* context, FILE* f) +{ + return EOF; +} +#endif + +SSIZE_T freerdp_interruptible_get_line(rdpContext* context, char** plineptr, size_t* psize, + FILE* stream) +{ + int c = 0; + char* n = NULL; + size_t step = 32; + size_t used = 0; + char* ptr = NULL; + size_t len = 0; + + if (!plineptr || !psize) + { + errno = EINVAL; + return -1; + } + + do + { + if (used + 2 >= len) + { + len += step; + n = realloc(ptr, len); + + if (!n) + { + return -1; + } + + ptr = n; + } + + c = freerdp_interruptible_getc(context, stream); + if (c != EOF) + ptr[used++] = (char)c; + } while ((c != '\n') && (c != '\r') && (c != EOF)); + + ptr[used] = '\0'; + if (c == EOF) + { + free(ptr); + return EOF; + } + *plineptr = ptr; + *psize = used; + return used; +} |