/* * Rename this process by changing the ps.ros.Argv vector * Try to put the name of the service in ps.ros.Argv[0], Argv[1] * until either the service name is exhausted or we run out * of ps.ros.Argv's. * The rest of ps.ros.Argv is cleared to spaces */ static void rename_process( const char *name ) { const char *from = name ; char *to = ps.ros.Argv[ 0 ] ; int tmp_index = 1 ; while ( *from != NUL ) { if ( *to != NUL ) *to++ = *from++ ; else if ( tmp_index < ps.ros.Argc ) to = ps.ros.Argv[ tmp_index++ ] ; else break ; } str_fill( to, ' ' ) ; while ( tmp_index < ps.ros.Argc ) str_fill( ps.ros.Argv[ tmp_index++ ], ' ' ) ; }
/* Fill up the string from a given double precision floating point number */ void str_double(str_t *str, const double lf) { char buf[32]; snprintf(buf, 32, "%g", lf); str_fill(str, buf, 0); }
/* Fill up the string from a given unsigned integer */ void str_uint(str_t *str, const unsigned int ui) { char buf[32]; snprintf(buf, 32, "%u", ui); str_fill(str, buf, 0); }
/* Fill up the string from a given integer */ void str_int(str_t *str, const int i) { char buf[32]; snprintf(buf, 32, "%i", i); str_fill(str, buf, 0); }
static int get_next_inet_entry( int fd, pset_h sconfs, struct service_config *defaults) { char *p; str_h strp; char *line = next_line(fd); struct service_config *scp; unsigned u, i; const char *func = "get_next_inet_entry"; char *name = NULL, *rpcvers = NULL, *rpcproto = NULL; char *group, *proto, *stype; const struct name_value *nvp; struct protoent *pep ; struct passwd *pw ; struct group *grp ; const char *dot = "."; const char *slash = "/"; pset_h args; if( line == CHAR_NULL ) return -2; strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ; if( strp == NULL ) { parsemsg( LOG_CRIT, func, "inetd.conf - str_parse failed" ) ; return( -1 ) ; } if( (args = pset_create(10,10)) == NULL ) { out_of_memory(func); return -1; } /* Break the line into components, based on spaces */ while( (p = str_component( strp )) ) { if( pset_add(args, p) == NULL ) { parsemsg( LOG_CRIT, func, ES_NOMEM ); pset_destroy(args); return -1; } } str_endparse( strp ); /* get the service name */ name = new_string((char *)pset_pointer( args, 0 )); if( name == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Invalid service name" ); pset_destroy(args); return -1; } /* Check to find the '/' for specifying RPC version numbers */ if( (rpcvers = strstr(name, slash)) != NULL ) { *rpcvers = '\0'; rpcvers++; } scp = sc_alloc( name ); if( scp == NULL ) { pset_destroy(args); free( name ); return -1; } /* * sc_alloc makes its own copy of name. At this point, sc_alloc worked * so we will free our copy to avoid leaks. */ free( name ); /* Replicate inetd behavior in this regard. Also makes sure the * service actually works on system where setgroups(0,NULL) doesn't * work. */ SC_GROUPS(scp) = YES; SC_SPECIFY( scp, A_GROUPS ); /* Get the socket type (stream dgram) */ stype = (char *)pset_pointer(args, 1); if( stype == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Invalid socket type" ); pset_destroy(args); sc_free(scp); return -1; } nvp = nv_find_value( socket_types, stype ); if( nvp == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Bad socket type: %s", p); pset_destroy(args); sc_free(scp); return -1; } SC_SOCKET_TYPE(scp) = nvp->value; /* Get the protocol type */ proto = (char *)pset_pointer(args,2); if( strstr(proto, "rpc") != NULL ) { int rpcmin, rpcmax; struct rpc_data *rdp = SC_RPCDATA( scp ) ; if( rpcvers == NULL ) { pset_destroy(args); sc_free(scp); return -1; /* uh oh */ } p = strchr(rpcvers, '-'); if( p && parse_int(rpcvers, 10, '-', &rpcmin) == 0 ) { if( parse_base10(p + 1, &rpcmax) || rpcmin > rpcmax ) { pset_destroy(args); sc_free(scp); return -1; } } else { if( parse_base10(rpcvers, &rpcmin) ) { pset_destroy(args); sc_free(scp); return -1; } rpcmax = rpcmin; } /* now have min and max rpc versions */ rdp->rd_min_version = rpcmin; rdp->rd_max_version = rpcmax; rpcproto = strstr(proto, slash); if( rpcproto == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - bad rpc version numbers" ); pset_destroy(args); sc_free(scp); return -1; } *rpcproto = '\0'; rpcproto++; proto = rpcproto; /* Set the RPC type field */ nvp = nv_find_value( service_types, "RPC" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_TYPE(scp), nvp->value); } if ( ( pep = getprotobyname( proto ) ) == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Protocol %s not in /etc/protocols", proto ) ; pset_destroy(args); sc_free(scp); return -1; } SC_PROTONAME(scp) = new_string( proto ) ; if ( SC_PROTONAME(scp) == NULL ) { out_of_memory( func ) ; pset_destroy(args); sc_free(scp); return -1; } SC_PROTOVAL(scp) = pep->p_proto; SC_SPECIFY(scp, A_PROTOCOL); /* Get the wait attribute */ p = (char *)pset_pointer(args, 3); if ( p == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - No value specified for wait" ); sc_free(scp); return -1; } if ( EQ( p, "wait" ) ) SC_WAIT(scp) = YES ; else if ( EQ( p, "nowait" ) ) SC_WAIT(scp) = NO ; else parsemsg( LOG_ERR, func, "inetd.conf - Bad value for wait: %s", p ) ; /* Get the user to run as */ p = (char *)pset_pointer(args, 4); if ( p == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" ); sc_free(scp); return -1; } if( (group = strstr(p, dot)) ) { *group = '\0'; group++; grp = (struct group *)getgrnam( (char *)group ) ; if ( grp == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Unknown group: %s", group ) ; pset_destroy(args); sc_free(scp); return -1; } SC_GID(scp) = ((struct group *)grp)->gr_gid; SC_SPECIFY( scp, A_GROUP ); } pw = getpwnam( p ); if ( pw == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - Unknown user: %s", p ) ; pset_destroy(args); sc_free(scp); return -1; } str_fill( pw->pw_passwd, ' ' ); SC_UID(scp) = pw->pw_uid; SC_USER_GID(scp) = pw->pw_gid; /* Get server name, or flag as internal */ p = (char *)pset_pointer(args, 5); if ( p == NULL ) { parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" ); sc_free(scp); return -1; } if( EQ( p, "internal" ) ) { nvp = nv_find_value( service_types, "INTERNAL" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_TYPE(scp), nvp->value); if( EQ( SC_NAME(scp), "time" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("time-stream"); else SC_ID(scp) = new_string("time-dgram"); } if( EQ( SC_NAME(scp), "daytime" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("daytime-stream"); else SC_ID(scp) = new_string("daytime-dgram"); } if( EQ( SC_NAME(scp), "chargen" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("chargen-stream"); else SC_ID(scp) = new_string("chargen-dgram"); } if( EQ( SC_NAME(scp), "echo" ) ) { if( EQ( proto, "stream" ) ) SC_ID(scp) = new_string("echo-stream"); else SC_ID(scp) = new_string("echo-dgram"); } if( EQ( SC_NAME(scp), "discard" ) ) { parsemsg(LOG_WARNING, func, "inetd.conf - service discard not supported"); pset_destroy(args); sc_free(scp); return -1; } } else { SC_SERVER(scp) = new_string( p ); if ( SC_SERVER(scp) == NULL ) { out_of_memory( func ) ; pset_destroy(args); sc_free(scp); return -1; } SC_SPECIFY( scp, A_SERVER); /* Get argv */ SC_SERVER_ARGV(scp) = (char **)argv_alloc(pset_count(args)+1); for( u = 0; u < pset_count(args)-6 ; u++ ) { p = new_string((char *)pset_pointer(args, u+6)); if( p == NULL ) { for ( i = 1 ; i < u ; i++ ) free( SC_SERVER_ARGV(scp)[i] ); free( SC_SERVER_ARGV(scp) ); pset_destroy(args); sc_free(scp); return -1; } SC_SERVER_ARGV(scp)[u] = p; } /* Set the reuse flag, as this is the default for inetd */ nvp = nv_find_value( service_flags, "REUSE" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_XFLAGS(scp), nvp->value); /* Set the NOLIBWRAP flag, since inetd doesn't have libwrap built in */ nvp = nv_find_value( service_flags, "NOLIBWRAP" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return -1; } M_SET(SC_XFLAGS(scp), nvp->value); /* Set the NAMEINARGS flag, as that's the default for inetd */ nvp = nv_find_value( service_flags, "NAMEINARGS" ); if ( nvp == NULL ) { parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ; pset_destroy(args); sc_free(scp); return (-1); } M_SET(SC_XFLAGS(scp), nvp->value); SC_SPECIFY( scp, A_SERVER_ARGS ); if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) ) SC_PRESENT( scp, A_ID ) ; else { out_of_memory( func ) ; pset_destroy(args); sc_free(scp); return -1; } } SC_SPECIFY( scp, A_PROTOCOL ); SC_SPECIFY( scp, A_USER ); SC_SPECIFY( scp, A_SOCKET_TYPE ); SC_SPECIFY( scp, A_WAIT ); if( ! pset_add(sconfs, scp) ) { out_of_memory( func ); pset_destroy(args); sc_free(scp); return -1; } pset_destroy(args); parsemsg( LOG_DEBUG, func, "added service %s", SC_NAME(scp)); return 0; }
static void set_credentials( const struct service_config *scp ) { const char *func = "set_credentials" ; if ( SC_SPECIFIED( scp, A_GROUP ) || SC_SPECIFIED( scp, A_USER ) ) { if ( ps.ros.is_superuser ) { gid_t gid = SC_GETGID( scp ) ; if ( setgid( gid ) == -1 ) { msg( LOG_ERR, func, "setgid failed: %m" ) ; _exit( 1 ) ; } #ifndef NO_INITGROUPS /* * Bug discovered by [email protected] (a bug fix was also provided; * a slightly modified version is included here): * initgroups was not being invoked to set the remaining * groups appropriately */ /* Solar Designer's groups fix */ if ( SC_SPECIFIED( scp, A_USER ) && SC_SPECIFIED( scp, A_GROUPS ) && scp->sc_groups == YES ) { struct passwd *pwd ; /* * Invoke getpwuid() to get the user's name. * * XXX: we should not need to invoke getpwuid(); we should * remember the user name in the configuration file. */ if ( ( pwd = getpwuid( SC_UID( scp ) ) ) == NULL ) { msg( LOG_ERR, func, "getpwuid( %d ) (service=%s) failed: %m", SC_UID( scp ), SC_ID( scp ) ) ; _exit( 1 ) ; } str_fill( pwd->pw_passwd, ' ' ); if ( initgroups( pwd->pw_name, pwd->pw_gid ) == -1 ) { msg( LOG_ERR, func, "initgroups( %s, %d ) failed: %m", pwd->pw_name, pwd->pw_gid ) ; _exit( 1 ) ; } } else { if ( setgroups( 0, NULL ) ) { msg( LOG_ERR, func, "setgroups( 0, NULL ) failed: %m" ) ; msg( LOG_ERR, func, "Your system may require that 'groups = yes' be defined for this service: %s", scp->sc_name); _exit( 1 ) ; } } #endif /* ! NO_INITGROUPS */ } } if ( SC_SPECIFIED( scp, A_USER ) ) { if ( setuid( SC_UID( scp ) ) == -1 ) { msg( LOG_ERR, func, "setuid failed: %m" ) ; _exit( 1 ) ; } } if ( SC_SPECIFIED( scp, A_UMASK ) ) umask(scp->sc_umask); }