diff options
Diffstat (limited to 'src/utils/io.c')
-rw-r--r-- | src/utils/io.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/utils/io.c b/src/utils/io.c new file mode 100644 index 0000000..3e372c2 --- /dev/null +++ b/src/utils/io.c @@ -0,0 +1,293 @@ +/** + * Copyright (C) 2006 International Business Machines + * Author(s): Trevor Highland <tshighla@us.ibm.com> + * Theresa Nelson <tmnelson@us.ibm.com> + * Tyler Hicks <tyhicks@ou.edu> + * + * I/O functions for mount helper + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <stdio.h> +#include <string.h> +#include <termios.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/mman.h> +#include "ecryptfs.h" +#include "io.h" + +static int disable_echo(struct termios *saved_settings) +{ + struct termios current_settings; + int rc = 0; + + rc = tcgetattr(0, ¤t_settings); + if (rc) + return rc; + *saved_settings = current_settings; + current_settings.c_lflag &= ~ECHO; + rc = tcsetattr(0, TCSANOW, ¤t_settings); + return rc; +} + +static int enable_echo(struct termios *saved_settings) +{ + return tcsetattr(0, TCSANOW, saved_settings); +} + +int mygetchar(void) +{ + int c = getchar(); + + if (c == '\r') + c = '\n'; + return c; +} + +int get_string_stdin(char **val, char *prompt, int echo) +{ +#define DEFAULT_STRING_LENGTH 16 + int count = 0; + struct termios saved_settings; + int length = DEFAULT_STRING_LENGTH; + char *temp; + int rc = 0; + int c; + + printf("%s: ", prompt); + temp = malloc(length); + if (!temp) { + rc = -ENOMEM; + goto out; + } + temp[0] = '\0'; + *val = temp; + if (!echo) { + rc = disable_echo(&saved_settings); + if (rc) + goto out; + } + do { + if (count == length) { + temp = malloc(length * 2); + if (!temp) { + rc = -ENOMEM; + goto out; + } + memcpy(temp, *val, length); + memset(*val, 0, length); + length *= 2; + free(*val); + *val = temp; + } + if ((c = mygetchar()) != EOF) + (*val)[count] = c; + else + (*val)[count] = '\n'; + count++; + } while(c != EOF && (*val)[count-1] != '\n'); + (*val)[count - 1] = '\0'; + if (!echo) { + printf("\n"); + rc = enable_echo(&saved_settings); + } + if (count == 1 && c == EOF) { + free(*val); + *val = NULL; + rc = -EIO; + } +out: + return rc; +} + +int get_string(char *val, int len, int echo) +{ + int count = 0; + struct termios saved_settings; + int rc = 0; + int c; + + if (echo == ECRYPTFS_ECHO_OFF) { + rc = disable_echo(&saved_settings); + if (rc) + goto out; + } + do { + if ((c = mygetchar()) != EOF) + val[count] = c; + else + val[count] = '\n'; + count++; + } while(c != EOF && val[count-1] != '\n' && (count < len)); + if (echo == ECRYPTFS_ECHO_OFF) { + printf("\n"); + rc = enable_echo(&saved_settings); + } + if (count == 1 && c == EOF) { + *val = '\0'; + rc = -EIO; + } else if (count > len) + val[len - 1] = '\0'; + else + val[count - 1] = '\0'; +out: + return rc; +} + +static inline int munch_newline(void) +{ + int c; + if ((c=mygetchar()) == '\n' || c == EOF) + return 0; + while ((c=mygetchar()) != '\n' && c != EOF); + return -1; +} + +int manager_menu(void) +{ + char str[8]; + int selection; + + printf("\neCryptfs key management menu\n"); + printf("-------------------------------\n"); + printf("\t%d. Add passphrase key to keyring\n", MME_MOUNT_PASSPHRASE); + printf("\t%d. Add public key to keyring\n", MME_MOUNT_PUBKEY); + printf("\t%d. Generate new public/private keypair\n", MME_GEN_PUBKEY); + printf("\t%d. Exit\n", MME_ABORT); +try_again: + printf("\nMake selection: "); + str[0] = mygetchar(); + if (munch_newline()) { + printf("Invalid selection\n"); + goto try_again; + } + str[strlen(str)] = '\0'; + selection = atoi(str); + switch (selection) { + case MME_MOUNT_PASSPHRASE: + case MME_MOUNT_PUBKEY: + case MME_GEN_PUBKEY: + case MME_ABORT: + break; + default: + printf("Invalid selection\n"); + goto try_again; + } + return selection; +} + +int read_passphrase_salt(char *pass, char *salt) +{ + char *confirmed_pass; + int rc = 0; + + confirmed_pass = malloc(ECRYPTFS_MAX_PASSWORD_LENGTH); + if (!confirmed_pass) { + rc = -ENOMEM; + ecryptfs_syslog(LOG_ERR, "Failed to allocate memory\n"); + goto ret; + } + mlock(confirmed_pass, ECRYPTFS_MAX_PASSWORD_LENGTH); + printf("\n\tMount-wide passphrase: "); + rc = get_string(pass, ECRYPTFS_MAX_PASSWORD_LENGTH, ECRYPTFS_ECHO_OFF); + if (rc) + goto out; + if (pass[0] == '\0') { + printf("Invalid passphrase. Aborting mount.\n"); + rc = -EINVAL; + goto out; + } + printf("\tConfirm passphrase: "); + rc = get_string(confirmed_pass, ECRYPTFS_MAX_PASSWORD_LENGTH, + ECRYPTFS_ECHO_OFF); + if (rc) { + ecryptfs_syslog(LOG_ERR, "Failed to read passphrase\n"); + goto out; + } + if (strcmp(pass, confirmed_pass) != 0) { + printf("Passphrase mismatch. Aborting mount\n"); + rc = -EINVAL; + goto out; + } + printf("\tUsing the default salt value\n"); +out: + memset(confirmed_pass, 0, ECRYPTFS_MAX_PASSWORD_LENGTH); + free(confirmed_pass); +ret: + return rc; +} + +int ecryptfs_select_key_mod(struct ecryptfs_key_mod **key_mod, + struct ecryptfs_ctx *ctx) +{ + int rc; + int key_mod_type; + int count; + struct ecryptfs_key_mod *curr; + char str[8]; + int default_key_mod = 1; + +prompt_user: + count = 1; + curr = ctx->key_mod_list_head.next; + if (!curr) { + rc = 1; + goto out; + } + if (!(curr->next)) + goto success; + printf("\nThe following PKI modules are available:\n"); + while (curr) { + printf("\t%i. %s\n", count, curr->alias); + count++; + curr = curr->next; + } + printf("\nSelect desired key module [%d]: ", default_key_mod); + if (fgets(str, 4, stdin) == NULL) { + printf("\nError reading input\n"); + rc = -EIO; + goto out; + } + printf("\n"); + str[strlen(str)] = '\0'; + if (str[0] == '\n') + key_mod_type = default_key_mod; + else + key_mod_type = atoi(str); + if (key_mod_type < 1 || key_mod_type >= count) { + char *pch = strstr(str, "\n"); + + printf("Invalid selection\n"); + if (!pch) { + int ch; + + while ((ch = mygetchar()) != '\n' && ch != EOF); + } + goto prompt_user; + } + curr = ctx->key_mod_list_head.next; + while(key_mod_type > 1) { + curr = curr->next; + key_mod_type--; + } +success: + (*key_mod) = curr; + rc = 0; +out: + return rc; +} |