diff options
Diffstat (limited to 'cpukit/telnetd/check_passwd.c')
-rw-r--r-- | cpukit/telnetd/check_passwd.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/cpukit/telnetd/check_passwd.c b/cpukit/telnetd/check_passwd.c new file mode 100644 index 0000000000..e1df00d2d9 --- /dev/null +++ b/cpukit/telnetd/check_passwd.c @@ -0,0 +1,200 @@ +/* $Id$ */ + +/* Read a password, encrypt it and compare to the encrypted + * password in the TELNETD_PASSWD environment variable. + * No password is required if TELNETD_PASSWD is unset + */ + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2003-2007 + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +#if !defined(INSIDE_TELNETD) && !defined(__rtems__) +#include <crypt.h> +#endif +#include <termios.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include "passwd.h" + +/* rtems has global filedescriptors but per-thread stdio streams... */ +#define STDI_FD fileno(stdin) +#define MAXPASSRETRY 3 + +extern char *__des_crypt_r(char *, char*, char*, int); + +#if !defined(INSIDE_TELNETD) +#define sockpeername(s,b,sz) (-1) +#endif + +#if defined(INSIDE_TELNETD) +static +#endif +int check_passwd(char *peername) +{ +char *pw; +int rval = -1, tmp, retries; +struct termios t,told; +int restore_flags = 0; +char buf[30], cryptbuf[21]; +char salt[3]; + + if ( !(pw=getenv("TELNETD_PASSWD")) || 0 == strlen(pw) ) +#ifdef TELNETD_DEFAULT_PASSWD + pw = TELNETD_DEFAULT_PASSWD; +#else + return 0; +#endif + + if ( tcgetattr(STDI_FD, &t) ) { + perror("check_passwd(): tcgetattr"); + goto done; + } + told = t; + t.c_lflag &= ~ECHO; + t.c_lflag &= ~ICANON; + t.c_cc[VTIME] = 255; + t.c_cc[VMIN] = 0; + + strncpy(salt,pw,2); + salt[2]=0; + + if ( tcsetattr(STDI_FD, TCSANOW, &t) ) { + perror("check_passwd(): tcsetattr"); + goto done; + } + restore_flags = 1; + + /* Here we ask for the password... */ + for ( retries = MAXPASSRETRY; retries > 0; retries-- ) { + fflush(stdin); + fprintf(stderr,"Password:"); + fflush(stderr); + if ( 0 == fgets(buf,sizeof(buf),stdin) ) { + /* 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('?',stdin) >= 0) + fgetc(stdin); + goto done; + } + fputc('\n',stderr); + tmp = strlen(buf); + while ( tmp > 0 && ('\n' == buf[tmp-1] || '\r' == buf[tmp-1]) ) { + buf[--tmp]=0; + } + if ( !strcmp(__des_crypt_r(buf, salt, cryptbuf, sizeof(cryptbuf)), pw) ) { + rval = 0; + break; + } + fprintf(stderr,"Incorrect Password.\n"); + sleep(2); + } + + if ( 0 == retries ) { + syslog( LOG_AUTHPRIV | LOG_WARNING, + "telnetd: %i wrong passwords entered from %s", + MAXPASSRETRY, + peername ? peername : "<UNKNOWN>"); + } + +done: + /* what to do if restoring the flags fails?? */ + if (restore_flags) + tcsetattr(STDI_FD, TCSANOW, &told); + + if (rval) { + sleep(2); + } + return rval; +} + +#if !defined(INSIDE_TELNETD) && !defined(__rtems__) +int +main(int argc, char **argv) +{ +char *str, *enc=0; +int ch; + +while ( (ch=getopt(argc, argv, "g:")) > 0 ) { + switch (ch) { + default: + fprintf(stderr,"Unknown option\n"); + return(1); + + case 'g': + printf("Generated encrypted password: '%s'\n", (enc=crypt(optarg,"td"))); + break; + + } +} +if (argc>optind && !enc) { + enc=argv[optind]; +} +if (enc) { + str = malloc(strlen(enc) + 30); + sprintf(str,"TELNETD_PASSWD=%s",enc); + putenv(str); +} +if (check_passwd(-1)) { + fprintf(stderr,"check_passwd() failed\n"); +} +return 0; +} + +#endif |