1 /*
2 * (c) Copyright 1992 by Panagiotis Tsirigotis
3 * (c) Sections Copyright 1998-2001 by Rob Braun
4 * All rights reserved. The file named COPYRIGHT specifies the terms
5 * and conditions for redistribution.
6 */
7
8
9 #include "config.h"
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <errno.h>
15 #include <time.h>
16 #include <syslog.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #ifdef HAVE_NETDB_H
20 #include <netdb.h>
21 #endif
22
23 #include "str.h"
24 #include "pset.h"
25 #include "sio.h"
26 #include "builtins.h"
27 #include "msg.h"
28 #include "connection.h"
29 #include "server.h"
30 #include "service.h"
31 #include "sconf.h"
32 #include "main.h"
33 #include "util.h"
34 #include "xconfig.h"
35 #include "state.h"
36 #include "libportable.h"
37 #include "signals.h"
38 #include "nvlists.h"
39 #include "child.h"
40 #include "access.h"
41
42 #define BUFFER_SIZE 1024
43
44 static void stream_echo(const struct server *) ;
45 static void dgram_echo(const struct server *) ;
46 static void stream_discard(const struct server *) ;
47 static void dgram_discard(const struct server *) ;
48 static void stream_time(const struct server *) ;
49 static void dgram_time(const struct server *) ;
50 static void stream_daytime(const struct server *) ;
51 static void dgram_daytime(const struct server *) ;
52 static void stream_chargen(const struct server *) ;
53 static void dgram_chargen(const struct server *) ;
54 static void tcpmux_handler(const struct server *) ;
55
56 /*
57 * SG - This is the call sequence to get to a built-in service
58 *
59 * main_loop main.c
60 * svc_request service.c
61 * svc_handle -- aka svc_handler_func -- aka svc_generic_handler service.c
62 * server_run server.c
63 * server_internal server.c
64 * SC_INTERNAL service.h
65 * BUILTIN_INVOKE sc_conf.h
66 * sc_builtin -- index into builtin_services builtins.c
67 */
68
69 static const struct builtin_service builtin_services[] =
70 {
71 { "echo", SOCK_STREAM, { stream_echo, FORK } },
72 { "echo", SOCK_DGRAM, { dgram_echo, NO_FORK } },
73 { "discard", SOCK_STREAM, { stream_discard, FORK } },
74 { "discard", SOCK_DGRAM, { dgram_discard, NO_FORK } },
75 { "time", SOCK_STREAM, { stream_time, NO_FORK } },
76 { "time", SOCK_DGRAM, { dgram_time, NO_FORK } },
77 { "daytime", SOCK_STREAM, { stream_daytime, NO_FORK } },
78 { "daytime", SOCK_DGRAM, { dgram_daytime, NO_FORK } },
79 { "chargen", SOCK_STREAM, { stream_chargen, FORK } },
80 { "chargen", SOCK_DGRAM, { dgram_chargen, NO_FORK } },
81 { "sensor", SOCK_STREAM, { stream_discard, NO_FORK } },
82 { "sensor", SOCK_DGRAM, { dgram_discard, NO_FORK } },
83 { "tcpmux", SOCK_STREAM, { tcpmux_handler, FORK } },
84 { NULL, 0, { NULL, 0 } }
85 } ;
86
87
builtin_find(const char * service_name,int type)88 const builtin_s *builtin_find( const char *service_name, int type )
89 {
90 const builtin_s *bsp ;
91 const char *func = "builtin_find" ;
92
93 if ( (bsp = builtin_lookup( builtin_services, service_name, type )) )
94 return( bsp ) ;
95 else
96 {
97 const char *type_name;
98 const struct name_value *sock_type = nv_find_name( socket_types, type );
99 if (sock_type == NULL)
100 type_name = "Unknown socket type";
101 else
102 type_name = sock_type->name;
103 msg( LOG_ERR, func, "No such internal service: %s/%s - DISABLING",
104 service_name, type_name ) ;
105 return( NULL ) ;
106 }
107 }
108
109
builtin_lookup(const struct builtin_service services[],const char * service_name,int type)110 const builtin_s *builtin_lookup( const struct builtin_service services[],
111 const char *service_name,
112 int type )
113 {
114 const struct builtin_service *bsp ;
115
116 for ( bsp = services ; bsp->bs_name != NULL ; bsp++ )
117 if ( EQ( bsp->bs_name, service_name ) && bsp->bs_socket_type == type )
118 return( &bsp->bs_handle ) ;
119 return( NULL ) ;
120 }
121
122
123 /*
124 * The rest of this file contains the functions that implement the
125 * builtin services
126 */
127
128
stream_echo(const struct server * serp)129 static void stream_echo( const struct server *serp )
130 {
131 char buf[ BUFFER_SIZE ] ;
132 ssize_t cc ;
133 int descriptor = SERVER_FD( serp ) ;
134 struct service *svc = SERVER_SERVICE( serp ) ;;
135
136 if( SVC_WAITS( svc ) ) {
137 descriptor = accept(descriptor, NULL, NULL);
138 if ( descriptor == -1 ) {
139 if ((errno == EMFILE) || (errno == ENFILE))
140 cps_service_stop(svc, "no available descriptors");
141 return;
142 }
143 }
144
145 close_all_svc_descriptors();
146
147 for ( ;; )
148 {
149 cc = read( descriptor, buf, sizeof( buf ) ) ;
150 if ( cc == 0 )
151 break ;
152 if ( cc == (ssize_t)-1 ) {
153 if ( errno == EINTR )
154 continue ;
155 else
156 break ;
157 }
158
159 if ( write_buf( descriptor, buf, cc ) == FAILED )
160 break ;
161 }
162 if( SVC_WAITS( svc ) ) /* Service forks, so close it */
163 Sclose(descriptor);
164 }
165
dgram_echo(const struct server * serp)166 static void dgram_echo( const struct server *serp )
167 {
168 char buf[ DATAGRAM_SIZE ] ;
169 union xsockaddr lsin;
170 ssize_t cc ;
171 socklen_t sin_len = 0;
172 int descriptor = SERVER_FD( serp ) ;
173
174 if( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
175 sin_len = sizeof( struct sockaddr_in );
176 else if( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
177 sin_len = sizeof( struct sockaddr_in6 );
178
179 cc = recvfrom( descriptor, buf, sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len ) ;
180 if ( cc != (ssize_t)-1 ) {
181 (void) sendto( descriptor, buf, (size_t)cc, 0, SA( &lsin ), sizeof( lsin ) ) ;
182 }
183 }
184
stream_discard(const struct server * serp)185 static void stream_discard( const struct server *serp )
186 {
187 char buf[ BUFFER_SIZE ] ;
188 ssize_t cc ;
189 int descriptor = SERVER_FD( serp ) ;
190 struct service *svc = SERVER_SERVICE( serp ) ;;
191
192 if( SVC_WAITS( svc ) ) {
193 descriptor = accept(descriptor, NULL, NULL);
194 if ( descriptor == -1 ) {
195 if ((errno == EMFILE) || (errno == ENFILE))
196 cps_service_stop(svc, "no available descriptors");
197 return;
198 }
199 }
200
201 close_all_svc_descriptors();
202
203 for ( ;; )
204 {
205 cc = read( descriptor, buf, sizeof( buf ) ) ;
206 if ( (cc == 0) || ((cc == (ssize_t)-1) && (errno != EINTR)) )
207 break ;
208 }
209 if( SVC_WAITS( svc ) ) /* Service forks, so close it */
210 Sclose(descriptor);
211 }
212
213
dgram_discard(const struct server * serp)214 static void dgram_discard( const struct server *serp )
215 {
216 char buf[ 1 ] ;
217
218 (void) recv( SERVER_FD( serp ), buf, sizeof( buf ), 0 ) ;
219 }
220
221
222 /*
223 * Generate the current time using the SMTP format:
224 * 02 FEB 1991 12:31:42 MST
225 *
226 * The result is placed in buf.
227 * buflen is a value-result parameter. It indicates the size of
228 * buf and on exit it has the length of the string placed in buf.
229 */
daytime_protocol(char * buf,unsigned int * buflen)230 static void daytime_protocol( char *buf, unsigned int *buflen )
231 {
232 static const char *month_name[] =
233 {
234 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
235 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
236 } ;
237 time_t now ;
238 struct tm *tmp ;
239 int size = *buflen ;
240 #ifdef HAVE_STRFTIME
241 int cc ;
242 #endif
243
244 (void) time( &now ) ;
245 tmp = localtime( &now ) ;
246 #ifndef HAVE_STRFTIME
247 strx_print( buflen, buf, size,
248 "%02d %s %d %02d:%02d:%02d %s\r\n",
249 tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
250 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_zone ) ;
251 #else
252 cc = strx_nprint( buf, size,
253 "%02d %s %d %02d:%02d:%02d",
254 tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
255 tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
256 if ( cc >= 0 ) {
257 *buflen = cc ;
258 size -= cc ;
259 cc = strftime( &buf[ *buflen ], (size_t)size, " %Z\r\n", tmp ) ;
260 *buflen += cc ;
261 }
262 #endif
263 }
264
265
stream_daytime(const struct server * serp)266 static void stream_daytime( const struct server *serp )
267 {
268 char time_buf[ BUFFER_SIZE ] ;
269 unsigned int buflen = sizeof( time_buf ) ;
270 int descriptor = SERVER_FD( serp ) ;
271 struct service *svc = SERVER_SERVICE( serp ) ;;
272
273 if( SVC_WAITS( svc ) ) {
274 descriptor = accept(descriptor, NULL, NULL);
275 if ( descriptor == -1 ) {
276 if ((errno == EMFILE) || (errno == ENFILE))
277 cps_service_stop(svc, "no available descriptors");
278 return;
279 }
280 }
281 daytime_protocol( time_buf, &buflen ) ;
282 (void) write_buf( descriptor, time_buf, (int)buflen ) ;
283 Sclose(descriptor);
284 }
285
286
dgram_daytime(const struct server * serp)287 static void dgram_daytime( const struct server *serp )
288 {
289 char time_buf[ BUFFER_SIZE ] ;
290 union xsockaddr lsin ;
291 socklen_t sin_len = 0 ;
292 unsigned int buflen = sizeof( time_buf ) ;
293 int descriptor = SERVER_FD( serp ) ;
294 ssize_t val;
295
296 if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
297 sin_len = sizeof( struct sockaddr_in );
298 else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
299 sin_len = sizeof( struct sockaddr_in6 );
300
301 val = recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
302 (struct sockaddr *)( &lsin ), &sin_len );
303 if ( val == (ssize_t)-1 )
304 return ;
305
306 daytime_protocol( time_buf, &buflen ) ;
307
308 (void) sendto( descriptor, time_buf, buflen, 0, SA(&lsin), sizeof( lsin ) ) ;
309 }
310
311
312 #define TIME_OFFSET 2208988800UL
313
314 /*
315 * We always report the time as 32 bits in network-byte-order
316 */
time_protocol(unsigned char * timep)317 static void time_protocol( unsigned char *timep )
318 {
319 time_t now ;
320 unsigned long base1900;
321
322 (void) time( &now ) ;
323 base1900 = (unsigned long)now + TIME_OFFSET ;
324 timep[0] = base1900 >> 24;
325 timep[1] = base1900 >> 16;
326 timep[2] = base1900 >> 8;
327 timep[3] = base1900;
328
329 }
330
331
stream_time(const struct server * serp)332 static void stream_time( const struct server *serp )
333 {
334 unsigned char time_buf[4];
335 int descriptor = SERVER_FD( serp );
336 struct service *svc = SERVER_SERVICE( serp );
337
338 if( SVC_WAITS( svc ) ) {
339 descriptor = accept(descriptor, NULL, NULL);
340 if ( descriptor == -1 ) {
341 if ((errno == EMFILE) || (errno == ENFILE))
342 cps_service_stop(svc, "no available descriptors");
343 return;
344 }
345 }
346
347 time_protocol( time_buf ) ;
348 (void) write_buf( descriptor, (char *) time_buf, 4 ) ;
349
350 Sclose(descriptor);
351 }
352
353
dgram_time(const struct server * serp)354 static void dgram_time( const struct server *serp )
355 {
356 char buf[ 1 ] ;
357 unsigned char time_buf[4];
358 union xsockaddr lsin ;
359 socklen_t sin_len = 0 ;
360 int fd = SERVER_FD( serp ) ;
361 ssize_t val;
362
363 if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
364 sin_len = sizeof( struct sockaddr_in );
365 else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
366 sin_len = sizeof( struct sockaddr_in6 );
367
368 val = recvfrom( fd, buf, sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len );
369 if ( val == (ssize_t)-1 )
370 return ;
371
372 time_protocol( time_buf ) ;
373 (void) sendto( fd, (char *) time_buf, 4, 0, SA( &lsin ), sin_len ) ;
374 }
375
376
377 #define ASCII_PRINTABLE_CHARS 94
378 #define LINE_LENGTH 72
379
380 #define RING_BUF_SIZE ASCII_PRINTABLE_CHARS + LINE_LENGTH
381
382 static char *ring_buf = NULL ;
383 static char *ring ;
384
385
386 #define ASCII_START ( ' ' + 1 )
387 #define ASCII_END 126
388
389 #define min( a, b ) ((a)<(b) ? (a) : (b))
390
generate_line(char * buf,unsigned int len)391 static char *generate_line( char *buf, unsigned int len )
392 {
393 unsigned int line_len = min( LINE_LENGTH, len-2 ) ;
394
395 if ( len < 2 ) /* If len < 2, min will be wrong */
396 return( NULL ) ;
397
398 /* This never gets freed. That's ok, because the reference to it is
399 * always kept for future reference.
400 */
401 if ( (ring_buf == NULL) && ((ring_buf = malloc(RING_BUF_SIZE)) == NULL) )
402 return(NULL);
403
404 if ( ring == NULL )
405 {
406 char ch ;
407 char *p ;
408
409 for ( p = ring_buf, ch = ASCII_START ;
410 p <= &ring_buf[ RING_BUF_SIZE - 1 ] ; p++ )
411 {
412 *p = ch++ ;
413 if ( ch == ASCII_END )
414 ch = ASCII_START ;
415 }
416 ring = ring_buf ;
417 }
418 (void) memcpy( buf, ring, line_len ) ;
419 buf[ line_len ] = '\r' ;
420 buf[ line_len+1 ] = '\n' ;
421
422 ring++ ;
423 if ( &ring_buf[ RING_BUF_SIZE - 1 ] - ring + 1 < LINE_LENGTH )
424 ring = ring_buf ;
425 return( buf ) ;
426 }
427
428
stream_chargen(const struct server * serp)429 static void stream_chargen( const struct server *serp )
430 {
431 char line_buf[ LINE_LENGTH+2 ] ;
432 int descriptor = SERVER_FD( serp ) ;
433 struct service *svc = SERVER_SERVICE( serp );
434
435 if( SVC_WAITS( svc ) ) {
436 descriptor = accept(descriptor, NULL, NULL);
437 if ( descriptor == -1 ) {
438 if ((errno == EMFILE) || (errno == ENFILE))
439 cps_service_stop(svc, "no available descriptors");
440 return;
441 }
442 }
443
444 (void) shutdown( descriptor, 0 ) ;
445 close_all_svc_descriptors();
446
447 for ( ;; )
448 {
449 if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
450 break ;
451 if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
452 break ;
453 }
454 if( SVC_WAITS( svc ) ) /* Service forks, so close it */
455 Sclose(descriptor);
456 }
457
458
dgram_chargen(const struct server * serp)459 static void dgram_chargen( const struct server *serp )
460 {
461 char buf[ BUFFER_SIZE ] ;
462 char *p ;
463 unsigned int len ;
464 union xsockaddr lsin ;
465 socklen_t sin_len = 0 ;
466 int fd = SERVER_FD( serp ) ;
467 unsigned int left = sizeof( buf ) ;
468 ssize_t val;
469
470 if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
471 sin_len = sizeof( struct sockaddr_in );
472 else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
473 sin_len = sizeof( struct sockaddr_in6 );
474
475 val = recvfrom( fd, buf, (size_t)sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len );
476 if ( val == (ssize_t)-1 )
477 return ;
478
479 #if BUFFER_SIZE < LINE_LENGTH+2
480 bad_variable = 1 ; /* this will cause a compilation error */
481 #endif
482
483 for ( p = buf ; left > 2 ; left -= len, p += len )
484 {
485 len = min( LINE_LENGTH+2, left ) ;
486 if ( generate_line( p, len ) == NULL )
487 break ;
488 }
489 (void) sendto( fd, buf, (size_t)(p-buf), 0, SA( &lsin ), sin_len ) ;
490 }
491
492
493 /* Handle a request for a tcpmux service.
494 * It's helpful to remember here that we are now a child of the original
495 * xinetd process. We were forked to keep the parent from blocking
496 * when we try to read the service name off'n the socket connection.
497 * Serp still points to an actual tcpmux 'server', or at least the
498 * service pointer of serp is valid.
499 */
500
tcpmux_handler(const struct server * serp)501 static void tcpmux_handler( const struct server *serp )
502 {
503 char svc_name[ BUFFER_SIZE ] ;
504 int cc ;
505 int descriptor = SERVER_FD( serp ) ;
506 const struct service *svc = SERVER_SERVICE( serp ) ;
507 unsigned u;
508 struct service *sp = NULL;
509 struct server server, *nserp;
510 struct service_config *scp = NULL;
511
512 close_all_svc_descriptors();
513
514 /* Read in the name of the service in the format "svc_name\r\n".
515 *
516 * XXX: should loop on partial reads (could probably use Sread() if
517 * it wasn't thrown out of xinetd source code a few revisions back).
518 */
519 do
520 {
521 cc = read( descriptor, svc_name, sizeof( svc_name ) ) ;
522 } while (cc == -1 && errno == EINTR);
523
524 if ( cc <= 0 )
525 {
526 msg(LOG_ERR, "tcpmux_handler", "read failed");
527 exit(0);
528 }
529
530 if ( ( cc <= 2 ) ||
531 ( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) )
532 {
533 if ( debug.on )
534 msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format.");
535
536 exit(0);
537 }
538
539 svc_name[cc - 2] = '\0'; /* Remove \r\n for compare */
540
541 if ( debug.on )
542 {
543 msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.",
544 cc, svc_name);
545 }
546
547 /* Search the services for the a match on name.
548 */
549
550 for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
551 {
552 sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
553
554 if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 )
555 {
556 /* Found the pointer. Validate its type.
557 */
558 scp = SVC_CONF( sp );
559
560 if ( ! SVC_IS_MUXCLIENT( sp ) && ! SVC_IS_MUXPLUSCLIENT( sp ) )
561 {
562 if ( debug.on )
563 {
564 msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.",
565 svc_name);
566 }
567 continue;
568 }
569
570 /* Send the accept string if we're a PLUS (+) client.
571 */
572
573 if ( SVC_IS_MUXPLUSCLIENT( sp ) )
574 {
575 if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) !=
576 sizeof( TCPMUX_ACK ) )
577 {
578 msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.",
579 svc_name);
580 exit(0);
581 }
582 }
583 break; /* Time to get on with the service */
584 }
585 continue; /* Keep looking */
586 }
587
588 if ( u >= pset_count( SERVICES( ps ) ) )
589 {
590 if ( debug.on )
591 {
592 msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.",
593 svc_name);
594 }
595
596 /* If a service was not found, we should say so. */
597 if ( Swrite( descriptor, TCPMUX_NOT_FOUND, sizeof( TCPMUX_NOT_FOUND ) ) !=
598 sizeof ( TCPMUX_NOT_FOUND ) )
599 {
600 msg(LOG_ERR, "tcpmux_handler", "Not found write failed for %s.",
601 svc_name);
602 exit(0);
603 }
604
605 /* Flush and exit, nothing to do */
606 Sflush( descriptor );
607 Sclose( descriptor );
608 exit(0);
609 }
610
611 if( SVC_WAITS( svc ) ) /* Service forks, so close it */
612 Sclose(descriptor);
613
614 server.svr_sp = sp;
615 server.svr_conn = SERVER_CONNECTION(serp);
616 nserp = server_alloc(&server);
617 if( SC_IS_INTERNAL( scp ) ) {
618 SC_INTERNAL(scp, nserp);
619 } else {
620 child_process(nserp);
621 }
622 }
623
624