From 8ad6681b6bb601c670726ca36c924f5852d01efd Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 25 Sep 2007 17:14:01 +0000 Subject: 2007-09-25 Joel Sherrill * telnetd/README, telnetd/pty.c, telnetd/pty.h, telnetd/telnetd.c, telnetd/telnetd.h: telnetd rewrite. * telnetd/check_passwd.c, telnetd/des.c, telnetd/genpw.c: New files. --- cpukit/telnetd/telnetd.c | 442 ++++++++++++++++++++++++----------------------- 1 file changed, 225 insertions(+), 217 deletions(-) (limited to 'cpukit/telnetd/telnetd.c') diff --git a/cpukit/telnetd/telnetd.c b/cpukit/telnetd/telnetd.c index 24282059aa..ba3d10f25c 100644 --- a/cpukit/telnetd/telnetd.c +++ b/cpukit/telnetd/telnetd.c @@ -78,15 +78,15 @@ extern int telnet_pty_initialize(); extern int telnet_pty_finalize(); struct shell_args { - char *devname; - void *arg; - char peername[16]; - char delete_myself; + char *devname; + void *arg; + char peername[16]; + char delete_myself; }; typedef union uni_sa { - struct sockaddr_in sin; - struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr sa; } uni_sa; static int sockpeername(int sock, char *buf, int bufsz); @@ -113,35 +113,35 @@ socklen_t /* 4.6 doesn't have socklen_t */ uint32_t #endif - size_adr = sizeof(srv->sin); + size_adr = sizeof(srv->sin); int acp_sock; - acp_sock = accept(des_socket,&srv->sa,&size_adr); + acp_sock = accept(des_socket,&srv->sa,&size_adr); - if (acp_sock<0) { - perror("telnetd:accept"); - goto bailout; - }; + if (acp_sock<0) { + perror("telnetd:accept"); + goto bailout; + }; - if ( !(rval=telnet_get_pty(acp_sock)) ) { - syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY"); - /* NOTE: failing 'do_get_pty()' closed the socket */ - goto bailout; - } + if ( !(rval=telnet_get_pty(acp_sock)) ) { + syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY"); + /* NOTE: failing 'do_get_pty()' closed the socket */ + goto bailout; + } - if (sockpeername(acp_sock, peername, sz)) - strncpy(peername, "", sz); + if (sockpeername(acp_sock, peername, sz)) + strncpy(peername, "", sz); #ifdef PARANOIA - syslog(LOG_DAEMON | LOG_INFO, - "telnetd: accepted connection from %s on %s", - peername, - rval); + syslog(LOG_DAEMON | LOG_INFO, + "telnetd: accepted connection from %s on %s", + peername, + rval); #endif bailout: - return rval; + return rval; } @@ -149,14 +149,14 @@ static void release_a_Connection(char *devname, char *peername, FILE **pstd, int { #ifdef PARANOIA - syslog( LOG_DAEMON | LOG_INFO, - "telnetd: releasing connection from %s on %s", - peername, - devname ); + syslog( LOG_DAEMON | LOG_INFO, + "telnetd: releasing connection from %s on %s", + peername, + devname ); #endif - while (--n>=0) - if (pstd[n]) fclose(pstd[n]); + while (--n>=0) + if (pstd[n]) fclose(pstd[n]); } @@ -169,17 +169,17 @@ socklen_t /* 4.6 doesn't have socklen_t */ uint32_t #endif - len = sizeof(peer.sin); + len = sizeof(peer.sin); int rval = sock < 0; - if ( !rval) - rval = getpeername(sock, &peer.sa, &len); + if ( !rval) + rval = getpeername(sock, &peer.sa, &len); - if ( !rval ) - rval = !inet_ntop( AF_INET, &peer.sin.sin_addr, buf, bufsz ); + if ( !rval ) + rval = !inet_ntop( AF_INET, &peer.sin.sin_addr, buf, bufsz ); - return rval; + return rval; } #if 1 @@ -205,136 +205,144 @@ int i=1; int size_adr; struct shell_args *arg; - if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) { - perror("telnetd:socket"); - telnetd_task_id=0; - rtems_task_delete(RTEMS_SELF); - }; - setsockopt(des_socket,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i)); - - memset(&srv,0,sizeof(srv)); - srv.sin.sin_family=AF_INET; - srv.sin.sin_port=htons(23); - size_adr=sizeof(srv.sin); - if ((bind(des_socket,&srv.sa,size_adr))<0) { - perror("telnetd:bind"); - close(des_socket); - telnetd_task_id=0; - rtems_task_delete(RTEMS_SELF); - }; - if ((listen(des_socket,5))<0) { - perror("telnetd:listen"); - close(des_socket); - telnetd_task_id=0; - rtems_task_delete(RTEMS_SELF); - }; - - /* we don't redirect stdio as this probably - * was started from the console anyways.. - */ - do { - devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername)); - - if ( !devname ) { - /* if something went wrong, sleep for some time */ - sleep(10); - continue; - } - if ( telnetd_dont_spawn ) { - if ( 0 == check_passwd(peername) ) - telnetd_shell(devname, telnetd_shell_arg); - } else { - arg = malloc( sizeof(*arg) ); - - arg->devname = devname; - arg->arg = telnetd_shell_arg; - strncpy(arg->peername, peername, sizeof(arg->peername)); - - if ( !telnetd_spawn_task(&devname[5], telnetd_task_priority, telnetd_stack_size, spawned_shell, arg) ) { - - FILE *dummy; - - if ( telnetd_spawn_task != telnetd_dflt_spawn ) { - fprintf(stderr,"Telnetd: Unable to spawn child task\n"); - } - - /* hmm - the pty driver slot can only be - * released by opening and subsequently - * closing the PTY - this also closes - * the underlying socket. So we mock up - * a stream... - */ - - if ( !(dummy=fopen(devname,"r+")) ) - perror("Unable to dummy open the pty, losing a slot :-("); - release_a_Connection(devname, peername, &dummy, 1); - free(arg); - sleep(2); /* don't accept connections too fast */ + if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) { + perror("telnetd:socket"); + telnetd_task_id=0; + rtems_task_delete(RTEMS_SELF); + }; + setsockopt(des_socket,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i)); + + memset(&srv,0,sizeof(srv)); + srv.sin.sin_family=AF_INET; + srv.sin.sin_port=htons(23); + size_adr=sizeof(srv.sin); + if ((bind(des_socket,&srv.sa,size_adr))<0) { + perror("telnetd:bind"); + close(des_socket); + telnetd_task_id=0; + rtems_task_delete(RTEMS_SELF); + }; + if ((listen(des_socket,5))<0) { + perror("telnetd:listen"); + close(des_socket); + telnetd_task_id=0; + rtems_task_delete(RTEMS_SELF); + }; + + /* we don't redirect stdio as this probably + * was started from the console anyways.. + */ + do { + devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername)); + + if ( !devname ) { + /* if something went wrong, sleep for some time */ + sleep(10); + continue; + } + if ( telnetd_dont_spawn ) { + if ( 0 == check_passwd(peername) ) + telnetd_shell(devname, telnetd_shell_arg); + } else { + arg = malloc( sizeof(*arg) ); + + arg->devname = devname; + arg->arg = telnetd_shell_arg; + strncpy(arg->peername, peername, sizeof(arg->peername)); + + if ( !telnetd_spawn_task(&devname[5], telnetd_task_priority, telnetd_stack_size, spawned_shell, arg) ) { + + FILE *dummy; + + if ( telnetd_spawn_task != telnetd_dflt_spawn ) { + fprintf(stderr,"Telnetd: Unable to spawn child task\n"); + } + + /* hmm - the pty driver slot can only be + * released by opening and subsequently + * closing the PTY - this also closes + * the underlying socket. So we mock up + * a stream... + */ + + if ( !(dummy=fopen(devname,"r+")) ) + perror("Unable to dummy open the pty, losing a slot :-("); + release_a_Connection(devname, peername, &dummy, 1); + free(arg); + sleep(2); /* don't accept connections too fast */ } - } - } while(1); - /* TODO: how to free the connection semaphore? But then - - * stopping the daemon is probably only needed during - * development/debugging. - * Finalizer code should collect all the connection semaphore - * counts and eventually clean up... - */ - close(des_socket); - telnetd_task_id=0; + } + } while(1); + /* TODO: how to free the connection semaphore? But then - + * stopping the daemon is probably only needed during + * development/debugging. + * Finalizer code should collect all the connection semaphore + * counts and eventually clean up... + */ + close(des_socket); + telnetd_task_id=0; } /***********************************************************/ static int initialize_telnetd(void) { - - if (telnetd_task_id ) return RTEMS_RESOURCE_IN_USE; - if (telnetd_stack_size<=0 ) telnetd_stack_size =32000; - - if ( !telnetd_spawn_task("TNTD", telnetd_task_priority, RTEMS_MINIMUM_STACK_SIZE, rtems_task_telnetd, 0) ) { - return -1; - } - return 0; + + if (telnetd_task_id ) return RTEMS_RESOURCE_IN_USE; + if (telnetd_stack_size<=0 ) telnetd_stack_size =32000; + + if ( !telnetd_spawn_task("TNTD", telnetd_task_priority, RTEMS_MINIMUM_STACK_SIZE, rtems_task_telnetd, 0) ) { + return -1; + } + return 0; } /***********************************************************/ -int startTelnetd(void (*cmd)(char *, void *), void *arg, int dontSpawn, int stack, int priority) +int rtems_telnetd_initialize( + void (*cmd)(char *, void *), + void *arg, + int dontSpawn, + size_t stack, + rtems_task_priority priority +) { - rtems_status_code sc; - - printf("This is rtems-telnetd (modified by Till Straumann)\n"); - printf("$Id$\n"); - printf("Release $Name$\n"); - - if ( !telnetd_shell && !cmd ) { - fprintf(stderr,"startTelnetd(): setup error - NO SHELL; bailing out\n"); - return 1; - } - - if (telnetd_task_id) { - fprintf(stderr,"ERROR:telnetd already started\n"); - return 1; - }; - - if ( !telnet_pty_initialize() ) { - fprintf(stderr,"PTY driver probably not properly registered\n"); - return 1; - } - - if (cmd) - telnetd_shell = cmd; - telnetd_shell_arg = arg; - telnetd_stack_size = stack; - if ( !priority ) { - priority = rtems_bsdnet_config.network_task_priority; - } - if ( priority < 2 ) - priority=100; - telnetd_task_priority = priority; - telnetd_dont_spawn = dontSpawn; - - sc=initialize_telnetd(); + rtems_status_code sc; + +#if 0 + printf("This is rtems-telnetd (modified by Till Straumann)\n"); + printf("$Id$\n"); + printf("Release $Name$\n"); +#endif + + if ( !telnetd_shell && !cmd ) { + fprintf(stderr,"startTelnetd(): setup error - NO SHELL; bailing out\n"); + return 1; + } + + if (telnetd_task_id) { + fprintf(stderr,"ERROR:telnetd already started\n"); + return 1; + }; + + if ( !telnet_pty_initialize() ) { + fprintf(stderr,"PTY driver probably not properly registered\n"); + return 1; + } + + if (cmd) + telnetd_shell = cmd; + telnetd_shell_arg = arg; + telnetd_stack_size = stack; + if ( !priority ) { + priority = rtems_bsdnet_config.network_task_priority; + } + if ( priority < 2 ) + priority=100; + telnetd_task_priority = priority; + telnetd_dont_spawn = dontSpawn; + + sc=initialize_telnetd(); if (sc!=RTEMS_SUCCESSFUL) return sc; - printf("rtems_telnetd() started with stacksize=%u,priority=%d\n", + printf("rtems_telnetd() started with stacksize=%u,priority=%d\n", (unsigned)telnetd_stack_size,(int)telnetd_task_priority); - return 0; + return 0; } /* utility wrapper */ @@ -347,32 +355,32 @@ FILE *ostd[3]={ stdin, stdout, stderr }; int i=0; struct shell_args *arg = targ; - sc=rtems_libio_set_private_env(); + sc=rtems_libio_set_private_env(); - /* newlib hack/workaround. Before we change stdin/out/err we must make + /* newlib hack/workaround. Before we change stdin/out/err we must make * sure the internal data are initialized (fileno(stdout) has this sideeffect). - * This should probably be done from RTEMS' libc support layer... - * (T.S., newlibc-1.13; 2005/10) + * This should probably be done from RTEMS' libc support layer... + * (T.S., newlibc-1.13; 2005/10) */ - fileno(stdout); + fileno(stdout); - if (RTEMS_SUCCESSFUL != sc) { - rtems_error(sc,"rtems_libio_set_private_env"); - goto cleanup; - } + if (RTEMS_SUCCESSFUL != sc) { + rtems_error(sc,"rtems_libio_set_private_env"); + goto cleanup; + } - /* redirect stdio */ - for (i=0; i<3; i++) { - if ( !(nstd[i]=fopen(arg->devname,"r+")) ) { - perror("unable to open stdio"); - goto cleanup; - } - } + /* redirect stdio */ + for (i=0; i<3; i++) { + if ( !(nstd[i]=fopen(arg->devname,"r+")) ) { + perror("unable to open stdio"); + goto cleanup; + } + } - stdin = nstd[0]; - stdout = nstd[1]; - stderr = nstd[2]; + stdin = nstd[0]; + stdout = nstd[1]; + stderr = nstd[2]; @@ -382,22 +390,22 @@ printf("hello\n"); write(fileno(stdout),"hellofd\n",8); #endif - /* call their routine */ - if ( 0 == check_passwd(arg->peername) ) - telnetd_shell(arg->devname, arg->arg); + /* call their routine */ + if ( 0 == check_passwd(arg->peername) ) + telnetd_shell(arg->devname, arg->arg); - stdin = ostd[0]; - stdout = ostd[1]; - stderr = ostd[2]; + stdin = ostd[0]; + stdout = ostd[1]; + stderr = ostd[2]; cleanup: - release_a_Connection(arg->devname, arg->peername, nstd, i); - free(arg); + release_a_Connection(arg->devname, arg->peername, nstd, i); + free(arg); } struct wrap_delete_args { - void (*t)(void *); - void *a; + void (*t)(void *); + void *a; }; static rtems_task @@ -407,12 +415,12 @@ struct wrap_delete_args *pwa = (struct wrap_delete_args *)arg; register void (*t)(void *) = pwa->t; register void *a = pwa->a; - /* free argument before calling function (which may never return if - * they choose to delete themselves) - */ - free(pwa); - t(a); - rtems_task_delete(RTEMS_SELF); + /* free argument before calling function (which may never return if + * they choose to delete themselves) + */ + free(pwa); + t(a); + rtems_task_delete(RTEMS_SELF); } void * @@ -423,32 +431,32 @@ rtems_id task_id; char nm[4] = {'X','X','X','X' }; struct wrap_delete_args *pwa = malloc(sizeof(*pwa)); - strncpy(nm, name, 4); - - if ( !pwa ) { - perror("Telnetd: no memory\n"); - return 0; - } - - pwa->t = fn; - pwa->a = fnarg; - - if ((sc=rtems_task_create( - rtems_build_name(nm[0], nm[1], nm[2], nm[3]), - (rtems_task_priority)priority, - stackSize, - RTEMS_DEFAULT_MODES, - RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, - &task_id)) || - (sc=rtems_task_start( - task_id, - wrap_delete, - (rtems_task_argument)pwa))) { - free(pwa); - rtems_error(sc,"Telnetd: spawning task failed"); - return 0; - } - return (void*)task_id; + strncpy(nm, name, 4); + + if ( !pwa ) { + perror("Telnetd: no memory\n"); + return 0; + } + + pwa->t = fn; + pwa->a = fnarg; + + if ((sc=rtems_task_create( + rtems_build_name(nm[0], nm[1], nm[2], nm[3]), + (rtems_task_priority)priority, + stackSize, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, + &task_id)) || + (sc=rtems_task_start( + task_id, + wrap_delete, + (rtems_task_argument)pwa))) { + free(pwa); + rtems_error(sc,"Telnetd: spawning task failed"); + return 0; + } + return (void*)task_id; } /* convenience routines for CEXP (retrieve stdio descriptors -- cgit v1.2.3