From 2649eef33ab4947ad690a90e381056e285d46635 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 27 Mar 2009 15:31:52 +0000 Subject: 2009-03-27 Sebastian Huber * Makefile.am, preinstall.am, libmisc/Makefile.am, libmisc/shell/shell.c, libmisc/shell/shell.h, telnetd/check_passwd.c, telnetd/telnetd.c, telnetd/telnetd.h: Generalized login check. * libmisc/shell/login.h, libmisc/shell/login_check.c, libmisc/shell/login_prompt.c: New files. * libmisc/stackchk/check.c: Changed format for blown stack message. * libcsupport/src/libio_sockets.c: Removed superfluous cast. * libnetworking/rtems/ftpfs.h: Documentation. --- cpukit/libmisc/shell/login.h | 56 +++++++++++++ cpukit/libmisc/shell/login_check.c | 58 +++++++++++++ cpukit/libmisc/shell/login_prompt.c | 162 ++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 cpukit/libmisc/shell/login.h create mode 100644 cpukit/libmisc/shell/login_check.c create mode 100644 cpukit/libmisc/shell/login_prompt.c diff --git a/cpukit/libmisc/shell/login.h b/cpukit/libmisc/shell/login.h new file mode 100644 index 0000000000..3e107825d4 --- /dev/null +++ b/cpukit/libmisc/shell/login.h @@ -0,0 +1,56 @@ +/** + * @file + * + * @author Sebastian Huber + * + * @brief Login types and functions. + */ + +/* + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * Based on work from Chris Johns, Fernando Ruiz and Till Straumann. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef RTEMS_LOGIN_H +#define RTEMS_LOGIN_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef bool (*rtems_login_check)( + const char * /* user */, + const char * /* passphrase */ +); + +bool rtems_shell_login_prompt( + FILE *in, + FILE *out, + const char *device, + rtems_login_check check +); + +bool rtems_shell_login_check( + const char *user, + const char *passphrase +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* RTEMS_LOGIN_H */ diff --git a/cpukit/libmisc/shell/login_check.c b/cpukit/libmisc/shell/login_check.c new file mode 100644 index 0000000000..066ab16b61 --- /dev/null +++ b/cpukit/libmisc/shell/login_check.c @@ -0,0 +1,58 @@ +/** + * @file + * + * @author Sebastian Huber + * + * @brief Shell login check function. + */ + +/* + * Copyright (c) 2009 + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * Based on work from Chris Johns, Fernando Ruiz and Till Straumann. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include +#include + +#include +#include +#include + +bool rtems_shell_login_check( + const char *user, + const char *passphrase +) +{ + struct passwd *pw = getpwnam( user); + + /* Valid user? */ + if (pw != NULL && strcmp( pw->pw_passwd, "!") != 0) { + setuid( pw->pw_uid); + setgid( pw->pw_gid); + rtems_current_user_env->euid = 0; + rtems_current_user_env->egid = 0; + chown( rtems_current_shell_env->devname, pw->pw_uid, 0); + rtems_current_user_env->euid = pw->pw_uid; + rtems_current_user_env->egid = pw->pw_gid; + if (strcmp( pw->pw_passwd, "*") == 0) { + /* TODO: /etc/shadow */ + return true; + } else { + /* TODO: crypt() */ + return true; + } + } + + return false; +} diff --git a/cpukit/libmisc/shell/login_prompt.c b/cpukit/libmisc/shell/login_prompt.c new file mode 100644 index 0000000000..fd347fb728 --- /dev/null +++ b/cpukit/libmisc/shell/login_prompt.c @@ -0,0 +1,162 @@ +/** + * @file + * + * @author Sebastian Huber + * + * @brief Shell login prompt functions. + */ + +/* + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * Based on work from Chris Johns, Fernando Ruiz and Till Straumann. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include +#include +#include + +#include + +static int rtems_shell_discard( int c, FILE *stream) +{ + return c; +} + +static void rtems_shell_get_text( + FILE *in, + FILE *out, + char *line, + size_t size +) +{ + int fd_in = fileno( in); + int (*put)( int, FILE *) = + out != NULL && isatty( fd_in) + ? fputc + : rtems_shell_discard; + size_t i = 0; + + if (size < 1) { + return; + } + + tcdrain( fd_in); + if (out != NULL){ + tcdrain( fileno( out)); + } + + while (true) { + int c = fgetc( in); + + switch (c) { + case EOF: + /* Here comes an ugly hack: The Termios driver's read() handler returns + * 0 to the C library's fgets() if it times out. fgets() interprets + * this (correctly) as EOF, a condition we want to undo since it's not + * really true since we really have a read error (Termios bug?). + * + * As a workaround we push something back and read it again. This + * should simply reset the EOF condition. + */ + if (ungetc( '?', in) == '?') { + fgetc( in); + } + break; + case '\n': + case '\r': + put( '\n', out); + line [i] = '\0'; + return; + case 127: + case '\b': + if (i > 0) { + put( '\b', out); + put( ' ', out); + put( '\b', out); + --i; + } else { + put( '\a', out); + } + break; + default: + if (!iscntrl( c)) { + if (i < size - 1) { + line [i] = (char) c; + ++i; + put( c, out); + } else { + put( '\a', out); + } + } else { + put( '\a', out); + } + break; + } + } +} + +bool rtems_shell_login_prompt( + FILE *in, + FILE *out, + const char *device, + rtems_login_check check +) +{ + int fd_in = fileno( in); + struct termios termios_previous; + bool restore_termios = false; + int i = 0; + bool result = false; + + if (tcgetattr( fd_in, &termios_previous) == 0) { + struct termios termios_new = termios_previous; + + termios_new.c_lflag &= ~ECHO; + termios_new.c_lflag &= ~ICANON; + termios_new.c_cc [VTIME] = 255; + termios_new.c_cc [VMIN] = 0; + + restore_termios = tcsetattr( fd_in, TCSANOW, &termios_new) == 0; + } + + for (i = 0; i < 3; ++i) { + char user [32]; + char passphrase [128]; + + fprintf( out, "%s login: ", device); + fflush( out); + rtems_shell_get_text( in, out, user, sizeof( user)); + + fflush( in); + fprintf( out, "Password: "); + fflush( out); + rtems_shell_get_text( in, NULL, passphrase, sizeof( passphrase)); + fputc( '\n', out); + + result = check( user, passphrase); + if (result) { + break; + } + + fprintf( out, "Login incorrect\n\n"); + sleep( 2); + } + + if (restore_termios) { + /* What to do if restoring the flags fails? */ + tcsetattr( fd_in, TCSANOW, &termios_previous); + } + + return result; +} -- cgit v1.2.3