/* $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 , 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 #endif #include #include #include #include #include #include #include #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 : ""); } 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