Changeset 8a775c27 in rtems for cpukit/telnetd
- Timestamp:
- Mar 27, 2009, 1:45:31 PM (11 years ago)
- Branches:
- 4.10, 4.11, master
- Children:
- 2649eef
- Parents:
- 8916bdc7
- Location:
- cpukit/telnetd
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
cpukit/telnetd/check_passwd.c
r8916bdc7 r8a775c27 1 1 /* $Id$ */ 2 2 3 /* Read a password, encrypt it and compare to the encrypted 4 * password in the TELNETD_PASSWD environment variable. 5 * No password is required if TELNETD_PASSWD is unset 6 */ 7 8 /* 3 /* 9 4 * Authorship 10 5 * ---------- … … 12 7 * Till Straumann <strauman@slac.stanford.edu>, 2003-2007 13 8 * Stanford Linear Accelerator Center, Stanford University. 14 * 9 * 15 10 * Acknowledgement of sponsorship 16 11 * ------------------------------ … … 18 13 * the Stanford Linear Accelerator Center, Stanford University, 19 14 * under Contract DE-AC03-76SFO0515 with the Department of Energy. 20 * 15 * 21 16 * Government disclaimer of liability 22 17 * ---------------------------------- … … 27 22 * disclosed, or represents that its use would not infringe privately owned 28 23 * rights. 29 * 24 * 30 25 * Stanford disclaimer of liability 31 26 * -------------------------------- 32 27 * Stanford University makes no representations or warranties, express or 33 28 * implied, nor assumes any liability for the use of this software. 34 * 29 * 35 30 * Stanford disclaimer of copyright 36 31 * -------------------------------- 37 32 * Stanford University, owner of the copyright, hereby disclaims its 38 33 * copyright and all other rights in this software. Hence, anyone may 39 * freely use it for any purpose without restriction. 40 * 34 * freely use it for any purpose without restriction. 35 * 41 36 * Maintenance of notices 42 37 * ---------------------- … … 47 42 * software made or distributed by the recipient that contains a copy or 48 43 * derivative of this software. 49 * 44 * 50 45 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 51 */ 46 * 47 * Copyright (c) 2009 48 * embedded brains GmbH 49 * Obere Lagerstr. 30 50 * D-82178 Puchheim 51 * Germany 52 * <rtems@embedded-brains.de> 53 * 54 * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>. 55 * 56 * The license and distribution terms for this file may be 57 * found in the file LICENSE in this distribution or at 58 * http://www.rtems.com/license/LICENSE. 59 */ 52 60 53 #if !defined(INSIDE_TELNETD) && !defined(__rtems__)54 #include <crypt.h>55 #endif56 61 #include <termios.h> 57 62 #include <errno.h> … … 62 67 #include <syslog.h> 63 68 69 #include <rtems/telnetd.h> 70 64 71 #include "passwd.h" 65 72 66 /* rtems has global filedescriptors but per-thread stdio streams... */ 67 #define STDI_FD fileno(stdin) 68 #define MAXPASSRETRY 3 73 char *__des_crypt_r( const char *, const char *, char *, int); 69 74 70 extern char *__des_crypt_r(char *, char*, char*, int); 75 /** 76 * @brief Standard Telnet login check that uses DES to encrypt the passphrase. 77 * 78 * Takes a @a passphrase, encrypts it and compares it to the encrypted 79 * passphrase in the @c TELNETD_PASSWD environment variable. No password is 80 * required if @c TELNETD_PASSWD is unset. The argument @a user is ignored. 81 */ 82 bool rtems_telnetd_login_check( 83 const char *user, 84 const char *passphrase 85 ) 86 { 87 char *pw = getenv( "TELNETD_PASSWD"); 88 char cryptbuf [21]; 89 char salt [3]; 71 90 72 #if !defined(INSIDE_TELNETD) 73 #define sockpeername(s,b,sz) (-1) 74 #endif 75 76 #if defined(INSIDE_TELNETD) 77 static 78 #endif 79 int check_passwd(char *peername) 80 { 81 char *pw; 82 int rval = -1, tmp, retries; 83 struct termios t,told; 84 int restore_flags = 0; 85 char buf[30], cryptbuf[21]; 86 char salt[3]; 87 88 if ( !(pw=getenv("TELNETD_PASSWD")) || 0 == strlen(pw) ) 89 #ifdef TELNETD_DEFAULT_PASSWD 90 pw = TELNETD_DEFAULT_PASSWD; 91 #else 92 return 0; 93 #endif 94 95 if ( tcgetattr(STDI_FD, &t) ) { 96 perror("check_passwd(): tcgetattr"); 97 goto done; 98 } 99 told = t; 100 t.c_lflag &= ~ECHO; 101 t.c_lflag &= ~ICANON; 102 t.c_cc[VTIME] = 255; 103 t.c_cc[VMIN] = 0; 104 105 strncpy(salt,pw,2); 106 salt[2]=0; 107 108 if ( tcsetattr(STDI_FD, TCSANOW, &t) ) { 109 perror("check_passwd(): tcsetattr"); 110 goto done; 111 } 112 restore_flags = 1; 113 114 /* Here we ask for the password... */ 115 for ( retries = MAXPASSRETRY; retries > 0; retries-- ) { 116 fflush(stdin); 117 fprintf(stderr,"Password:"); 118 fflush(stderr); 119 if ( 0 == fgets(buf,sizeof(buf),stdin) ) { 120 /* Here comes an ugly hack: 121 * The termios driver's 'read()' handler 122 * returns 0 to the c library's fgets if 123 * it times out. 'fgets' interprets this 124 * (correctly) as EOF, a condition we want 125 * to undo since it's not really true since 126 * we really have a read error (termios bug??) 127 * 128 * As a workaround we push something back and 129 * read it again. This should simply reset the 130 * EOF condition. 131 */ 132 if (ungetc('?',stdin) >= 0) 133 fgetc(stdin); 134 goto done; 135 } 136 fputc('\n',stderr); 137 tmp = strlen(buf); 138 while ( tmp > 0 && ('\n' == buf[tmp-1] || '\r' == buf[tmp-1]) ) { 139 buf[--tmp]=0; 140 } 141 if ( !strcmp(__des_crypt_r(buf, salt, cryptbuf, sizeof(cryptbuf)), pw) ) { 142 rval = 0; 143 break; 144 } 145 fprintf(stderr,"Incorrect Password.\n"); 146 sleep(2); 91 if (pw == NULL || strlen( pw) == 0) { 92 #ifdef TELNETD_DEFAULT_PASSWD 93 pw = TELNETD_DEFAULT_PASSWD; 94 #else 95 return true; 96 #endif 147 97 } 148 98 149 if ( 0 == retries ) { 150 syslog( LOG_AUTHPRIV | LOG_WARNING, 151 "telnetd: %i wrong passwords entered from %s", 152 MAXPASSRETRY, 153 peername ? peername : "<UNKNOWN>"); 154 } 99 strncpy( salt, pw, 2); 100 salt [2] = '\0'; 155 101 156 done: 157 /* what to do if restoring the flags fails?? */ 158 if (restore_flags) 159 tcsetattr(STDI_FD, TCSANOW, &told); 160 161 if (rval) { 162 sleep(2); 163 } 164 return rval; 102 return strcmp( 103 __des_crypt_r( passphrase, salt, cryptbuf, sizeof( cryptbuf)), 104 pw 105 ) == 0; 165 106 } 166 167 #if !defined(INSIDE_TELNETD) && !defined(__rtems__)168 int169 main(int argc, char **argv)170 {171 char *str, *enc=0;172 int ch;173 174 while ( (ch=getopt(argc, argv, "g:")) > 0 ) {175 switch (ch) {176 default:177 fprintf(stderr,"Unknown option\n");178 return(1);179 180 case 'g':181 printf("Generated encrypted password: '%s'\n", (enc=crypt(optarg,"td")));182 break;183 184 }185 }186 if (argc>optind && !enc) {187 enc=argv[optind];188 }189 if (enc) {190 str = malloc(strlen(enc) + 30);191 sprintf(str,"TELNETD_PASSWD=%s",enc);192 putenv(str);193 }194 if (check_passwd(-1)) {195 fprintf(stderr,"check_passwd() failed\n");196 }197 return 0;198 }199 200 #endif -
cpukit/telnetd/telnetd.c
r8916bdc7 r8a775c27 6 6 * Author: 17,may 2001 7 7 * 8 * WORK: fernando.ruiz@ctv.es 8 * WORK: fernando.ruiz@ctv.es 9 9 * HOME: correo@fernando-ruiz.com 10 10 * … … 16 16 * With register_telnetd() you add a new command in the shell to start 17 17 * this daemon interactively. (Login in /dev/console of course) 18 * 18 * 19 19 * Sorry but OOB is not still implemented. (This is the first version) 20 20 * … … 24 24 * program. 25 25 * 26 * This program is distributed in the hope that it will be useful, 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 29 * 30 * $Id$ 26 * Copyright (c) 2009 27 * embedded brains GmbH 28 * Obere Lagerstr. 30 29 * D-82178 Puchheim 30 * Germany 31 * <rtems@embedded-brains.de> 32 * 33 * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>. 34 * 35 * The license and distribution terms for this file may be 36 * found in the file LICENSE in this distribution or at 37 * http://www.rtems.com/license/LICENSE. 38 * 39 * $Id$ 31 40 */ 32 41 … … 74 83 static int sockpeername(int sock, char *buf, int bufsz); 75 84 76 static int initialize_telnetd(void); 77 static int telnetd_askForPassword; 78 79 void * telnetd_dflt_spawn( 85 void *telnetd_dflt_spawn( 80 86 const char *name, 81 87 unsigned priority, … … 86 92 87 93 /***********************************************************/ 88 rtems_id telnetd_task_id = 0; 89 uint32_t telnetd_stack_size = 32000; 90 rtems_task_priority telnetd_task_priority = 0; 91 bool telnetd_remain_on_caller_stdio = false; 92 void (*telnetd_shell)(char *, void*) = 0; 93 void *telnetd_shell_arg = NULL; 94 void * (*telnetd_spawn_task)( 94 static rtems_id telnetd_task_id = RTEMS_ID_NONE; 95 96 void *(*telnetd_spawn_task)( 95 97 const char *, 96 98 unsigned, 97 99 unsigned, 98 100 void (*)(void*), 99 void *) = telnetd_dflt_spawn; 101 void * 102 ) = telnetd_dflt_spawn; 100 103 101 104 static char *grab_a_Connection( … … 179 182 } 180 183 181 #if 1182 #define INSIDE_TELNETD183 #include "check_passwd.c"184 #else185 #define check_passwd(arg) 0186 #endif187 188 189 184 static void 190 185 spawned_shell(void *arg); … … 204 199 if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) { 205 200 perror("telnetd:socket"); 206 telnetd_task_id =0;201 telnetd_task_id = RTEMS_ID_NONE; 207 202 rtems_task_delete(RTEMS_SELF); 208 203 }; … … 216 211 perror("telnetd:bind"); 217 212 close(des_socket); 218 telnetd_task_id =0;213 telnetd_task_id = RTEMS_ID_NONE; 219 214 rtems_task_delete(RTEMS_SELF); 220 215 }; … … 222 217 perror("telnetd:listen"); 223 218 close(des_socket); 224 telnetd_task_id =0;219 telnetd_task_id = RTEMS_ID_NONE; 225 220 rtems_task_delete(RTEMS_SELF); 226 221 }; … … 230 225 */ 231 226 do { 232 if ( telnetd_remain_on_caller_stdio ) { 233 char device_name[32]; 234 ttyname_r( 1, device_name, sizeof(device_name) ); 235 if ( !telnetd_askForPassword || (0 == check_passwd(arg->peername)) ) 236 telnetd_shell(device_name, telnetd_shell_arg); 227 if (rtems_telnetd_config.keep_stdio) { 228 bool start = true; 229 char device_name [32]; 230 231 ttyname_r( 1, device_name, sizeof( device_name)); 232 if (rtems_telnetd_config.login_check != NULL) { 233 start = rtems_shell_login_prompt( 234 stdin, 235 stderr, 236 device_name, 237 rtems_telnetd_config.login_check 238 ); 239 } 240 if (start) { 241 rtems_telnetd_config.command( device_name, arg->arg); 242 } else { 243 syslog( 244 LOG_AUTHPRIV | LOG_WARNING, 245 "telnetd: to many wrong passwords entered from %s", 246 device_name 247 ); 248 } 237 249 } else { 238 250 devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername)); 239 251 240 252 if ( !devname ) { 241 242 243 253 /* if something went wrong, sleep for some time */ 254 sleep(10); 255 continue; 244 256 } 245 257 … … 247 259 248 260 arg->devname = devname; 249 arg->arg = telnetd_shell_arg;261 arg->arg = rtems_telnetd_config.arg; 250 262 strncpy(arg->peername, peername, sizeof(arg->peername)); 251 263 252 if ( !telnetd_spawn_task( &devname[5], telnetd_task_priority, 253 telnetd_stack_size, spawned_shell, arg) ) { 264 telnetd_task_id = (rtems_id) telnetd_spawn_task( 265 devname, 266 rtems_telnetd_config.priority, 267 rtems_telnetd_config.stack_size, 268 spawned_shell, 269 arg 270 ); 271 if (telnetd_task_id == RTEMS_ID_NONE) { 254 272 FILE *dummy; 255 273 … … 274 292 } while(1); 275 293 276 /* TODO: how to free the connection semaphore? But then - 294 /* TODO: how to free the connection semaphore? But then - 277 295 * stopping the daemon is probably only needed during 278 296 * development/debugging. … … 281 299 */ 282 300 close(des_socket); 283 telnetd_task_id=0; 284 } 285 286 /***********************************************************/ 287 static int initialize_telnetd(void) { 288 289 if (telnetd_task_id ) return RTEMS_RESOURCE_IN_USE; 290 if (telnetd_stack_size<=0 ) telnetd_stack_size =32000; 291 292 if ( !telnetd_spawn_task("TNTD", telnetd_task_priority, 293 RTEMS_MINIMUM_STACK_SIZE, rtems_task_telnetd, 0) ) { 294 return -1; 295 } 296 return 0; 297 } 298 299 /***********************************************************/ 300 int rtems_telnetd_initialize( 301 void (*cmd)(char *, void *), 302 void *arg, 303 bool remainOnCallerSTDIO, 304 size_t stack, 305 rtems_task_priority priority, 306 bool askForPassword 307 ) 308 { 309 rtems_status_code sc; 310 311 #if 0 312 printf("This is rtems-telnetd (modified by Till Straumann)\n"); 313 printf("$Id$\n"); 314 printf("Release $Name$\n"); 315 #endif 316 317 if ( !telnetd_shell && !cmd ) { 318 fprintf(stderr,"startTelnetd(): setup error - NO SHELL; bailing out\n"); 319 return 1; 320 } 321 322 if (telnetd_task_id) { 323 fprintf(stderr,"ERROR:telnetd already started\n"); 324 return 1; 325 }; 301 telnetd_task_id = RTEMS_ID_NONE; 302 } 303 304 rtems_status_code rtems_telnetd_initialize( void) 305 { 306 rtems_status_code sc = RTEMS_SUCCESSFUL; 307 308 if (telnetd_task_id != RTEMS_ID_NONE) { 309 fprintf(stderr, "telnetd already started\n"); 310 return RTEMS_RESOURCE_IN_USE; 311 } 312 313 if (rtems_telnetd_config.command == NULL) { 314 fprintf(stderr, "telnetd setup with invalid command\n"); 315 return RTEMS_IO_ERROR; 316 } 326 317 327 318 if ( !telnet_pty_initialize() ) { 328 fprintf(stderr,"PTY driver probably not properly registered\n"); 329 return 1; 330 } 331 332 telnetd_askForPassword = askForPassword; 333 334 if (cmd) 335 telnetd_shell = cmd; 336 telnetd_shell_arg = arg; 337 telnetd_stack_size = stack; 338 if ( !priority ) { 339 priority = rtems_bsdnet_config.network_task_priority; 340 } 341 if ( priority < 2 ) 342 priority = 100; 343 telnetd_task_priority = priority; 344 telnetd_remain_on_caller_stdio = remainOnCallerSTDIO; 345 346 sc = initialize_telnetd(); 347 if (sc != RTEMS_SUCCESSFUL) return sc; 348 349 if ( !telnetd_remain_on_caller_stdio ) 350 fprintf(stderr, "rtems_telnetd() started with stacksize=%u,priority=%d\n", 351 (unsigned)telnetd_stack_size,(int)telnetd_task_priority); 352 return 0; 319 fprintf(stderr, "telnetd cannot initialize PTY driver\n"); 320 return RTEMS_IO_ERROR; 321 } 322 323 /* Check priority */ 324 if (rtems_telnetd_config.priority <= 0) { 325 rtems_telnetd_config.priority = rtems_bsdnet_config.network_task_priority; 326 } 327 if (rtems_telnetd_config.priority < 2) { 328 rtems_telnetd_config.priority = 100; 329 } 330 331 /* Check stack size */ 332 if (rtems_telnetd_config.stack_size <= 0) { 333 rtems_telnetd_config.stack_size = 32 * 1024; 334 } 335 336 /* Spawn task */ 337 telnetd_task_id = (rtems_id) telnetd_spawn_task( 338 "TNTD", 339 rtems_telnetd_config.priority, 340 RTEMS_MINIMUM_STACK_SIZE, 341 rtems_task_telnetd, 342 0 343 ); 344 if (telnetd_task_id == RTEMS_ID_NONE) { 345 return RTEMS_IO_ERROR; 346 } 347 348 /* Print status */ 349 if (!rtems_telnetd_config.keep_stdio) { 350 fprintf( 351 stderr, 352 "telnetd started with stacksize = %u and priority = %d\n", 353 (unsigned) rtems_telnetd_config.stack_size, 354 (unsigned) rtems_telnetd_config.priority 355 ); 356 } 357 358 return RTEMS_SUCCESSFUL; 353 359 } 354 360 … … 362 368 int i=0; 363 369 struct shell_args *arg = targ; 370 bool login_failed = false; 371 bool start = true; 364 372 365 373 sc=rtems_libio_set_private_env(); … … 398 406 399 407 /* call their routine */ 400 if ( !telnetd_askForPassword || (0 == check_passwd(arg->peername)) ) 401 telnetd_shell(arg->devname, arg->arg); 408 if (rtems_telnetd_config.login_check != NULL) { 409 start = rtems_shell_login_prompt( 410 stdin, 411 stderr, 412 arg->devname, 413 rtems_telnetd_config.login_check 414 ); 415 login_failed = !start; 416 } 417 if (start) { 418 rtems_telnetd_config.command( arg->devname, arg->arg); 419 } 402 420 403 421 stdin = ostd[0]; 404 422 stdout = ostd[1]; 405 423 stderr = ostd[2]; 424 425 if (login_failed) { 426 syslog( 427 LOG_AUTHPRIV | LOG_WARNING, 428 "telnetd: to many wrong passwords entered from %s", 429 arg->peername 430 ); 431 } 406 432 407 433 cleanup: … … 434 460 { 435 461 rtems_status_code sc; 436 rtems_id task_id ;462 rtems_id task_id = RTEMS_ID_NONE; 437 463 char nm[4] = {'X','X','X','X' }; 438 464 struct wrap_delete_args *pwa = malloc(sizeof(*pwa)); … … 442 468 if ( !pwa ) { 443 469 perror("Telnetd: no memory\n"); 444 return 0;470 return (void *) RTEMS_ID_NONE; 445 471 } 446 472 … … 461 487 free(pwa); 462 488 rtems_error(sc,"Telnetd: spawning task failed"); 463 return 0;464 } 465 return (void *)task_id;489 return (void *) RTEMS_ID_NONE; 490 } 491 return (void *) task_id; 466 492 } 467 493 -
cpukit/telnetd/telnetd.h
r8916bdc7 r8a775c27 4 4 * Reworked by Till Straumann and .h overhauled by Joel Sherrill. 5 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 6 * Copyright (c) 2009 7 * embedded brains GmbH 8 * Obere Lagerstr. 30 9 * D-82178 Puchheim 10 * Germany 11 * <rtems@embedded-brains.de> 9 12 * 10 * $Id$ 13 * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>. 14 * 15 * The license and distribution terms for this file may be 16 * found in the file LICENSE in this distribution or at 17 * http://www.rtems.com/license/LICENSE. 18 * 19 * $Id$ 11 20 */ 12 21 … … 14 23 #define _RTEMS_TELNETD_H 15 24 25 #include <rtems.h> 26 #include <rtems/login.h> 27 16 28 #ifdef __cplusplus 17 29 extern "C" { 18 #endif 30 #endif 31 32 bool rtems_telnetd_login_check( 33 const char *user, 34 const char *passphrase 35 ); 19 36 20 37 /** 21 * This method initializes the telnetd subsystem. 38 * @brief Telnet command type. 39 */ 40 typedef void (*rtems_telnetd_command)( 41 char * /* device name */, 42 void * /* arg */ 43 ); 44 45 /** 46 * @brief Telnet configuration structure. 47 */ 48 typedef struct { 49 /** 50 * @brief Function invoked for each Telnet connection. 51 * 52 * The first parameter contains the device name. The second parameter 53 * contains the argument pointer of this configuration table. 54 */ 55 rtems_telnetd_command command; 56 57 /** 58 * @brief Argument for command function. 59 */ 60 void *arg; 61 62 /** 63 * @brief Task priority. 64 * 65 * If this parameter is equal to zero, then the priority of network task is 66 * used or 100 if this priority is less than two. 67 */ 68 rtems_task_priority priority; 69 70 /** 71 * @brief Task stack size. 72 */ 73 size_t stack_size; 74 75 /** 76 * @brief Login check function. 77 * 78 * Method used for login checks. Use @c NULL to disable a login check. 79 */ 80 rtems_login_check login_check; 81 82 /** 83 * @brief Keep standard IO of the caller. 84 * 85 * Telnet takes over the standard input, output and error associated with 86 * task, if this parameter is set to @c true. In this case, it will @b not 87 * listen on any sockets. When this parameter is @c false, Telnet will 88 * create other tasks for the shell which listen on sockets. 89 */ 90 bool keep_stdio; 91 } rtems_telnetd_config_table; 92 93 /** 94 * @brief Telnet configuration. 22 95 * 23 * @param[in] cmd is the function which is the "shell" telnetd invokes 24 * @param[in] arg is the context pointer to cmd 25 * @param[in] remainOnCallerSTDIO is set to TRUE if telnetd takes over the 26 * standard in, out and error associated with task. In this case, 27 * it will be NOT be listening on any sockets. When this parameters 28 * is FALSE the telnetd will create other tasks for the shell 29 * which listen on sockets. 30 * @param[in] stack is stack size of spawned task. 31 * @param[in] priority is the initial priority of spawned task(s). If 32 * this parameter is less than 2, then the default priority of 100 is used. 33 * @param[in] askForPassword is set to TRUE if telnetd is to ask for a 34 * password. This is set to FALSE to invoke "cmd" with no password check. 35 * This may be OK if "cmd" includes its own check and indeed the RTEMS Shell 36 * uses a login with a user name and password so this is the usual case. 96 * The application must provide this configuration table. It is used by 97 * rtems_telnetd_initialize() to configure the Telnet subsystem. Do not modify 98 * the entries after the intialization since it is used internally. 37 99 */ 38 int rtems_telnetd_initialize( 39 void (*cmd)(char *, void *), 40 void *arg, 41 bool remainOnCallerSTDIO,42 size_t stack,43 rtems_task_priority priority,44 bool askForPassword45 );100 extern rtems_telnetd_config_table rtems_telnetd_config; 101 102 /** 103 * @brief Initializes the Telnet subsystem. 104 * 105 * Uses the application provided @ref rtems_telnetd_config configuration table. 106 */ 107 rtems_status_code rtems_telnetd_initialize( void); 46 108 47 109 #ifdef __cplusplus 48 110 } 49 #endif 111 #endif 50 112 51 113 #endif
Note: See TracChangeset
for help on using the changeset viewer.