diff options
| -rw-r--r-- | include/libbb.h | 2 | ||||
| -rw-r--r-- | libbb/Makefile.in | 2 | ||||
| -rw-r--r-- | libbb/vfork_daemon_rexec.c | 27 | ||||
| -rw-r--r-- | miscutils/Config.in | 7 | ||||
| -rw-r--r-- | miscutils/crond.c | 411 | ||||
| -rw-r--r-- | networking/Config.in | 9 | ||||
| -rw-r--r-- | networking/Makefile.in | 7 | ||||
| -rw-r--r-- | networking/httpd.c | 64 | ||||
| -rw-r--r-- | networking/inetd.c | 24 | ||||
| -rw-r--r-- | sysklogd/klogd.c | 4 | ||||
| -rw-r--r-- | sysklogd/syslogd.c | 5 | 
11 files changed, 316 insertions, 246 deletions
| diff --git a/include/libbb.h b/include/libbb.h index a4d8c7196..6b75b8a89 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -453,4 +453,6 @@ extern llist_t *llist_add_to(llist_t *old_head, char *new_item);  void print_login_issue(const char *issue_file, const char *tty);  void print_login_prompt(void); +void vfork_daemon_rexec(int argc, char **argv, char *foreground_opt); +  #endif /* __LIBCONFIG_H__ */ diff --git a/libbb/Makefile.in b/libbb/Makefile.in index c4886e3ff..b60adc959 100644 --- a/libbb/Makefile.in +++ b/libbb/Makefile.in @@ -48,7 +48,7 @@ LIBBB_SRC:= \  	fclose_nonstdin.c fflush_stdout_and_exit.c getopt_ulflags.c \  	default_error_retval.c wfopen_input.c speed_table.c \  	perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c \ -	warn_ignoring_args.c concat_subpath_file.c +	warn_ignoring_args.c concat_subpath_file.c vfork_daemon_rexec.c  LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c new file mode 100644 index 000000000..c8f9d277e --- /dev/null +++ b/libbb/vfork_daemon_rexec.c @@ -0,0 +1,27 @@ +/* + * Rexec program for system have fork() as vfork() with foregound option + * Copyright (C) Vladminr Oleynik and many different people. + */ + +#include <unistd.h> +#include "libbb.h" + + +#if defined(__uClinux__) +void vfork_daemon_rexec(int argc, char **argv, char *foreground_opt) +{ +	char **vfork_args; +	int a = 0; + +	vfork_args = xcalloc(sizeof(char *), argc + 3); +	while(*argv) { +	    vfork_args[a++] = *argv; +	    argv++; +	} +	vfork_args[a] = foreground_opt; +	execvp("/proc/self/exe", vfork_args); +	vfork_args[0] = "/bin/busybox"; +	execv(vfork_args[0], vfork_args); +	bb_perror_msg_and_die("execv %s", vfork_args[0]); +} +#endif /* uClinux */ diff --git a/miscutils/Config.in b/miscutils/Config.in index b4a3475de..0c56f0ee9 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in @@ -19,6 +19,13 @@ config CONFIG_CROND  	  Crond is a background daemon that parses individual crontab  	  files and executes commands on behalf of the users in question. +config CONFIG_FEATURE_CROND_CALL_SENDMAIL +	bool "  Using /usr/sbin/sendmail?" +	default n +	depends on CONFIG_CROND +	help +	  Support call /usr/sbin/sendmail for send cmd outputs. +  config CONFIG_CRONTAB  	bool "crontab"  	default n diff --git a/miscutils/crond.c b/miscutils/crond.c index 9d9ecc290..198bc2d85 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -41,14 +41,11 @@  #ifndef TMPDIR  #define TMPDIR          "/var/spool/cron"  #endif -#ifndef LOG_FILE -#define LOG_FILE        "/var/log/cron" -#endif  #ifndef SENDMAIL  #define SENDMAIL        "/usr/sbin/sendmail"  #endif  #ifndef SENDMAIL_ARGS -#define SENDMAIL_ARGS   "-t", "-oem", "-i" +#define SENDMAIL_ARGS   "-ti", "oem"  #endif  #ifndef CRONUPDATE  #define CRONUPDATE      "cron.update" @@ -57,6 +54,7 @@  #define MAXLINES        256             /* max lines in non-root crontabs */  #endif +static const char def_sh[] = "/bin/sh";  typedef struct CronFile { @@ -71,7 +69,7 @@ typedef struct CronFile {  typedef struct CronLine {      struct CronLine *cl_Next;      char        *cl_Shell;      /* shell command                        */ -    int         cl_Pid;         /* running pid, 0, or armed (-1)        */ +    pid_t       cl_Pid;         /* running pid, 0, or armed (-1)        */      int         cl_MailFlag;    /* running pid is for mail              */      int         cl_MailPos;     /* 'empty file' size                    */      char        cl_Mins[60];    /* 0-59                                 */ @@ -92,13 +90,9 @@ static short DebugOpt;  #endif  static short LogLevel = 8; -static short ForegroundOpt; -static short LoggerOpt; -static const char  *LogFile = LOG_FILE; +static const char  *LogFile;  static const char  *CDir = CRONTABS; -static void log(int level, const char *ctl, ...); -static void log9(const char *ctl, ...);  static void startlogger(void);  static void CheckUpdates(void); @@ -106,14 +100,54 @@ static void SynchronizeDir(void);  static int TestJobs(time_t t1, time_t t2);  static void RunJobs(void);  static int CheckJobs(void); -static void RunJob(CronFile *file, CronLine *line); -static void EndJob(const CronFile *file, CronLine *line); + +static void RunJob(const char *user, CronLine *line); +#ifdef CONFIG_FEATURE_CROND_CALL_SENDMAIL +static void EndJob(const char *user, CronLine *line); +#else +#define EndJob(user, line)  line->cl_Pid = 0 +#endif  static void DeleteFile(const char *userName);  static CronFile *FileBase; +static void +log(const char *ctl, ...) +{ +    va_list va; +    int level = (int)(ctl[0] & 0xf); +    int type = level == 20 ? +		    LOG_ERR : ((ctl[0] & 0100) ? LOG_WARNING : LOG_NOTICE); + + +    va_start(va, ctl); +    if (level >= LogLevel) { + +#ifdef FEATURE_DEBUG_OPT +	if (DebugOpt) vfprintf(stderr, ctl, va); +	else +#endif +	    if (LogFile == 0) vsyslog(type, ctl, va); +	    else { +		 int  logfd; + +		 if ((logfd = open(LogFile, O_WRONLY|O_CREAT|O_APPEND, 600)) >= 0) { +		    vdprintf(logfd, ctl, va); +		    close(logfd); +#ifdef FEATURE_DEBUG_OPT +		 } else { +		    bb_perror_msg("Can't open log file"); +#endif +		} +	    } +    } +    va_end(va); +    if(ctl[0] & 0200) +	exit(20); +} +  int  crond_main(int ac, char **av)  { @@ -138,10 +172,8 @@ crond_main(int ac, char **av)  	    );      if(opt & 1)  	LogLevel = atoi(lopt); -    LoggerOpt = opt & 2; -    if(LoggerOpt) +    if(opt & 2)  	if (*Lopt != 0) LogFile = Lopt; -    ForegroundOpt = opt & 4;      if(opt & 32) {  	if (*copt != 0) CDir = copt;  	} @@ -157,7 +189,7 @@ crond_main(int ac, char **av)       */      if (chdir(CDir) != 0) -	bb_perror_msg_and_die("chdir"); +	bb_perror_msg_and_die("%s", CDir);      signal(SIGHUP,SIG_IGN);   /* hmm.. but, if kill -HUP original  				 * version - his died. ;( @@ -168,9 +200,15 @@ crond_main(int ac, char **av)       * optional detach from controlling terminal       */ -    if (ForegroundOpt == 0) { -	if(daemon(1, 0) < 0) +    if (!(opt & 4)) { +	if(daemon(1, 0) < 0) {  		bb_perror_msg_and_die("daemon"); +#if defined(__uClinux__) +	} else { +	    /* reexec for vfork() do continue parent */ +	    vfork_daemon_rexec(ac, av, "-f"); +	} +#endif /* uClinux */      }      (void)startlogger();                /* need if syslog mode selected */ @@ -180,7 +218,8 @@ crond_main(int ac, char **av)       *             of 1 second.       */ -    log(9,"%s " VERSION " dillon, started, log level %d\n", av[0], LogLevel); +    log("\011%s " VERSION " dillon, started, log level %d\n", bb_applet_name, +						LogLevel);      SynchronizeDir(); @@ -221,11 +260,11 @@ crond_main(int ac, char **av)  	    CheckUpdates();  #ifdef FEATURE_DEBUG_OPT  	    if (DebugOpt) -		log(5, "Wakeup dt=%d\n", dt); +		log("\005Wakeup dt=%d\n", dt);  #endif  	    if (dt < -60*60 || dt > 60*60) {  		t1 = t2; -		log9("time disparity of %d minutes detected\n", dt / 60); +		log("\111time disparity of %d minutes detected\n", dt / 60);  	    } else if (dt > 0) {  		TestJobs(t1, t2);  		RunJobs(); @@ -242,81 +281,10 @@ crond_main(int ac, char **av)  } -static void -vlog(int level, int MLOG_LEVEL, const char *ctl, va_list va) -{ -    char buf[1024]; -    int  logfd; - -    if (level >= LogLevel) { - -	vsnprintf(buf,sizeof(buf), ctl, va); -#ifdef FEATURE_DEBUG_OPT -	if (DebugOpt) fprintf(stderr,"%s",buf); -	else -#endif -	    if (LoggerOpt == 0) syslog(MLOG_LEVEL, "%s", buf); -	    else { -		 if ((logfd = open(LogFile,O_WRONLY|O_CREAT|O_APPEND,600)) >= 0){ -		    write(logfd, buf, strlen(buf)); -		    close(logfd); -		 } else -#ifdef FEATURE_DEBUG_OPT -		    bb_perror_msg("Can't open log file") -#endif -							; -	    } -    } -} - -/* -	set log_level=9 and log messages -*/ - -static void -log9(const char *ctl, ...) -{ -    va_list va; - -    va_start(va, ctl); -    vlog(9, LOG_WARNING, ctl, va); -    va_end(va); -} - -/* -	normal logger call point. -*/ - -static void -log(int level, const char *ctl, ...) -{ -    va_list va; - -    va_start(va, ctl); -    vlog(level, LOG_NOTICE, ctl, va); -    va_end(va); -} - +#if defined(FEATURE_DEBUG_OPT) || defined(CONFIG_FEATURE_CROND_CALL_SENDMAIL)  /* -	Original: void -		  logfd(int fd, const char *ctl, ...) -	Updated to: log_error (used by jobs.c) +    write to temp file..  */ - -static void -log_err(const char *ctl, ...) -{ -    va_list va; - -    va_start(va, ctl); -    vlog(20, LOG_ERR, ctl, va); -    va_end(va); -} - -/* -	used by jobs.c (write to temp file..) -*/ -  static void  fdprintf(int fd, const char *ctl, ...)  { @@ -326,10 +294,11 @@ fdprintf(int fd, const char *ctl, ...)      vdprintf(fd, ctl, va);      va_end(va);  } +#endif  static int -ChangeUser(const char *user, short dochdir) +ChangeUser(const char *user)  {      struct passwd *pas; @@ -338,58 +307,55 @@ ChangeUser(const char *user, short dochdir)       */      if ((pas = getpwnam(user)) == 0) { -	log(9, "failed to get uid for %s", user); +	log("\011failed to get uid for %s", user);  	return(-1);      }      setenv("USER", pas->pw_name, 1);      setenv("HOME", pas->pw_dir, 1); -    setenv("SHELL", "/bin/sh", 1); +    setenv("SHELL", def_sh, 1);      /*       * Change running state to the user in question       */      if (initgroups(user, pas->pw_gid) < 0) { -	log(9, "initgroups failed: %s %m", user); +	log("\011initgroups failed: %s %m", user);  	return(-1);      } -    if (setregid(pas->pw_gid, pas->pw_gid) < 0) { -	log(9, "setregid failed: %s %d", user, pas->pw_gid); +    /* drop all priviledges */ +    if (setgid(pas->pw_gid) < 0) { +	log("\011setgid failed: %s %d", user, pas->pw_gid);  	return(-1);      } -    if (setreuid(pas->pw_uid, pas->pw_uid) < 0) { -	log(9, "setreuid failed: %s %d", user, pas->pw_uid); +    if (setuid(pas->pw_uid) < 0) { +	log("\011setuid failed: %s %d", user, pas->pw_uid);  	return(-1);      } -    if (dochdir) {  	if (chdir(pas->pw_dir) < 0) { -	    log(8, "chdir failed: %s %s", user, pas->pw_dir); +	log("\011chdir failed: %s: %m", pas->pw_dir);  	    if (chdir(TMPDIR) < 0) { -		log(9, "chdir failed: %s %s", TMPDIR, user); +	    log("\011chdir failed: %s: %m", TMPDIR);  		return(-1);  	    }  	} -    }      return(pas->pw_uid);  }  static void  startlogger(void)  { +    if (LogFile == 0) +	openlog(bb_applet_name, LOG_CONS|LOG_PID, LOG_CRON); +#ifdef FEATURE_DEBUG_OPT +    else { /* test logfile */      int  logfd; -    if (LoggerOpt == 0) -	openlog(bb_applet_name, LOG_CONS|LOG_PID,LOG_CRON); - -    else { /* test logfile */ -	if ((logfd = open(LogFile,O_WRONLY|O_CREAT|O_APPEND,600)) >= 0) +	if ((logfd = open(LogFile, O_WRONLY|O_CREAT|O_APPEND, 600)) >= 0)  	   close(logfd);  	else -#ifdef FEATURE_DEBUG_OPT -	   printf("Failed to open log file '%s' reason: %m", LogFile) -#endif -									; +	   bb_perror_msg("Failed to open log file '%s' reason", LogFile);      } +#endif  } @@ -493,7 +459,7 @@ ParseField(char *user, char *ary, int modvalue, int off,  	 */  	if (skip == 0) { -	    log9("failed user %s parsing %s\n", user, base); +	    log("\111failed user %s parsing %s\n", user, base);  	    return(NULL);  	}  	if (*ptr == '-' && n2 < 0) { @@ -532,7 +498,7 @@ ParseField(char *user, char *ary, int modvalue, int off,  	    } while (n1 != n2 && --failsafe);  	    if (failsafe == 0) { -		log9("failed user %s parsing %s\n", user, base); +		log("\111failed user %s parsing %s\n", user, base);  		return(NULL);  	    }  	} @@ -544,7 +510,7 @@ ParseField(char *user, char *ary, int modvalue, int off,      }      if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') { -	log9("failed user %s parsing %s\n", user, base); +	log("\111failed user %s parsing %s\n", user, base);  	return(NULL);      } @@ -556,8 +522,8 @@ ParseField(char *user, char *ary, int modvalue, int off,  	int i;  	for (i = 0; i < modvalue; ++i) -	    log(5, "%d", ary[i]); -	log(5, "\n"); +	    log("\005%d", ary[i]); +	log("\005\n");      }  #endif @@ -636,7 +602,7 @@ SynchronizeFile(const char *fileName)  #ifdef FEATURE_DEBUG_OPT  		    if (DebugOpt) -			log9("User %s Entry %s\n", fileName, buf); +			log("\111User %s Entry %s\n", fileName, buf);  #endif  		    /* @@ -674,7 +640,7 @@ SynchronizeFile(const char *fileName)  #ifdef FEATURE_DEBUG_OPT  		    if (DebugOpt) { -			log9("    Command %s\n", ptr); +			log("\111    Command %s\n", ptr);  		    }  #endif @@ -686,7 +652,7 @@ SynchronizeFile(const char *fileName)  		FileBase = file;  		if (maxLines == 0 || maxEntries == 0) -		    log9("Maximum number of lines reached for user %s\n", fileName); +		    log("\111Maximum number of lines reached for user %s\n", fileName);  	    }  	    fclose(fi);  	} @@ -712,21 +678,17 @@ static void  SynchronizeDir(void)  {      /* -     * Attempt to delete the database.  Note that we have to make a copy -     * of the string +     * Attempt to delete the database.       */      for (;;) {  	CronFile *file; -	char *user;  	for (file = FileBase; file && file->cf_Deleted; file = file->cf_Next)  	    ;  	if (file == NULL)  	    break; -	user = strdup(file->cf_User); -	DeleteFile(user); -	free(user); +	DeleteFile(file->cf_User);      }      /* @@ -740,8 +702,7 @@ SynchronizeDir(void)      remove(CRONUPDATE);      if (chdir(CDir) < 0) { -	log9("unable to find %s\n", CDir); -	exit(20); +	log("\311unable to find %s\n", CDir);      }      {  	DIR *dir; @@ -754,12 +715,11 @@ SynchronizeDir(void)  		if (getpwnam(den->d_name))  		    SynchronizeFile(den->d_name);  		else -		    log(7, "ignoring %s\n", den->d_name); +		    log("\007ignoring %s\n", den->d_name);  	    }  	    closedir(dir);  	} else { -	    log9("Unable to open current dir!\n"); -	    exit(20); +	    log("\311Unable to open current dir!\n");  	}      }  } @@ -836,14 +796,14 @@ TestJobs(time_t t1, time_t t2)  	    for (file = FileBase; file; file = file->cf_Next) {  #ifdef FEATURE_DEBUG_OPT  		if (DebugOpt) -		    log(5, "FILE %s:\n", file->cf_User); +		    log("\005FILE %s:\n", file->cf_User);  #endif  		if (file->cf_Deleted)  		    continue;  		for (line = file->cf_LineBase; line; line = line->cl_Next) {  #ifdef FEATURE_DEBUG_OPT  		    if (DebugOpt) -			log(5, "    LINE %s\n", line->cl_Shell); +			log("\005    LINE %s\n", line->cl_Shell);  #endif  		    if (line->cl_Mins[tp->tm_min] &&  			line->cl_Hrs[tp->tm_hour] && @@ -852,10 +812,10 @@ TestJobs(time_t t1, time_t t2)  		    ) {  #ifdef FEATURE_DEBUG_OPT  			if (DebugOpt) -			    log(5, "    JobToDo: %d %s\n", line->cl_Pid, line->cl_Shell); +			    log("\005    JobToDo: %d %s\n", line->cl_Pid, line->cl_Shell);  #endif  			if (line->cl_Pid > 0) { -			    log(8, "    process already running: %s %s\n", +			    log("\010    process already running: %s %s\n",  				file->cf_User,  				line->cl_Shell  			    ); @@ -885,9 +845,9 @@ RunJobs(void)  	    for (line = file->cf_LineBase; line; line = line->cl_Next) {  		if (line->cl_Pid < 0) { -		    RunJob(file, line); +		    RunJob(file->cf_User, line); -		    log(8, "USER %s pid %3d cmd %s\n", +		    log("\010USER %s pid %3d cmd %s\n",  			file->cf_User,  			line->cl_Pid,  			line->cl_Shell @@ -926,7 +886,7 @@ CheckJobs(void)  		    int r = wait4(line->cl_Pid, &status, WNOHANG, NULL);  		    if (r < 0 || r == line->cl_Pid) { -			EndJob(file, line); +			EndJob(file->cf_User, line);  			if (line->cl_Pid)  			    file->cf_Running = 1;  		    } else if (r == 0) { @@ -941,83 +901,54 @@ CheckJobs(void)  } - +#ifdef CONFIG_FEATURE_CROND_CALL_SENDMAIL  static void -RunJob(CronFile *file, CronLine *line) +ForkJob(const char *user, CronLine *line, int mailFd, +	const char *prog, const char *cmd, const char *arg, const char *mailf)  { -    char mailFile[128]; -    int mailFd; - -    line->cl_Pid = 0; -    line->cl_MailFlag = 0; - -    /* -     * open mail file - owner root so nobody can screw with it. -     */ - -    snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", -	     file->cf_User, getpid()); -    mailFd = open(mailFile, O_CREAT|O_TRUNC|O_WRONLY|O_EXCL|O_APPEND, 0600); - -    if (mailFd >= 0) { -	line->cl_MailFlag = 1; -	fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", -	    file->cf_User, -	    line->cl_Shell -	); -	line->cl_MailPos = lseek(mailFd, 0, 1); -    } -      /*       * Fork as the user in question and run program       */ +    pid_t pid = fork(); -    if ((line->cl_Pid = fork()) == 0) { +    line->cl_Pid = pid; +    if (pid == 0) {  	/* -	 * CHILD, FORK OK +	 * CHILD  	 */  	/*  	 * Change running state to the user in question  	 */ -	if (ChangeUser(file->cf_User, 1) < 0) -	    return; +	if (ChangeUser(user) < 0) +	    exit(0);  #ifdef FEATURE_DEBUG_OPT  	if (DebugOpt) -	    log(5, "Child Running %s\n", line->cl_Shell); +	    log("\005Child Running %s\n", prog);  #endif -	/* -	 * stdin is already /dev/null, setup stdout and stderr -	 */ -  	if (mailFd >= 0) { -	    dup2(mailFd, 1); -	    dup2(mailFd, 2); +	    dup2(mailFd, mailf != NULL); +	    dup2((mailf ? mailFd : 1), 2);  	    close(mailFd); -	} else { -	    log_err("unable to create mail file user %s file %s, output to /dev/null\n", -		file->cf_User, -		mailFile -	    );  	} -	execl("/bin/sh", "/bin/sh", "-c", line->cl_Shell, NULL, NULL); -	log_err("unable to exec, user %s cmd /bin/sh -c %s\n", -	    file->cf_User, -	    line->cl_Shell -	); -	fdprintf(1, "Exec failed: /bin/sh -c %s\n", line->cl_Shell); +	execl(prog, prog, cmd, arg, NULL); +	log("\024unable to exec, user %s cmd %s %s %s\n", user, +	    prog, cmd, arg); +	if(mailf) +	    fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);  	exit(0); -    } else if (line->cl_Pid < 0) { +    } else if (pid < 0) {  	/* -	 * PARENT, FORK FAILED +	 * FORK FAILED  	 */ -	log_err("couldn't fork, user %s\n", file->cf_User); +	log("\024couldn't fork, user %s\n", user);  	line->cl_Pid = 0; -	remove(mailFile); -    } else { +	if(mailf) +	    remove(mailf); +    } else if(mailf) {  	/*  	 * PARENT, FORK SUCCESS  	 * @@ -1026,10 +957,9 @@ RunJob(CronFile *file, CronLine *line)  	char mailFile2[128];  	snprintf(mailFile2, sizeof(mailFile2), TMPDIR "/cron.%s.%d", -		file->cf_User, line->cl_Pid); -	rename(mailFile, mailFile2); +				    user, pid); +	rename(mailf, mailFile2);      } -      /*       * Close the mail file descriptor.. we can't just leave it open in       * a structure, closing it later, because we might run out of descriptors @@ -1039,12 +969,42 @@ RunJob(CronFile *file, CronLine *line)  	close(mailFd);  } +static void +RunJob(const char *user, CronLine *line) +{ +    char mailFile[128]; +    int mailFd; + +    line->cl_Pid = 0; +    line->cl_MailFlag = 0; + +    /* +     * open mail file - owner root so nobody can screw with it. +     */ + +    snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", +	     user, getpid()); +    mailFd = open(mailFile, O_CREAT|O_TRUNC|O_WRONLY|O_EXCL|O_APPEND, 0600); + +    if (mailFd >= 0) { +	line->cl_MailFlag = 1; +	fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user, +						    line->cl_Shell); +	line->cl_MailPos = lseek(mailFd, 0, 1); +    } else { +	    log("\024unable to create mail file user %s file %s, output to /dev/null\n", +			user, mailFile); +    } + +    ForkJob(user, line, mailFd, def_sh, "-c", line->cl_Shell, mailFile); +} +  /*   * EndJob - called when job terminates and when mail terminates   */  static void -EndJob(const CronFile *file, CronLine *line) +EndJob(const char *user, CronLine *line)  {      int mailFd;      char mailFile[128]; @@ -1065,7 +1025,7 @@ EndJob(const CronFile *file, CronLine *line)       */      snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", -	     file->cf_User, line->cl_Pid); +	     user, line->cl_Pid);      line->cl_Pid = 0;      if (line->cl_MailFlag != 1) @@ -1093,46 +1053,47 @@ EndJob(const CronFile *file, CronLine *line)  	close(mailFd);  	return;      } +    ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL); +} +#else +/* crond whithout sendmail */ -    if ((line->cl_Pid = fork()) == 0) { +static void +RunJob(const char *user, CronLine *line) +{  	/* -	 * CHILD, FORK OK +     * Fork as the user in question and run program  	 */ +    pid_t pid = fork(); +    if (pid == 0) {  	/* -	 * change user id - no way in hell security can be compromised -	 * by the mailing and we already verified the mail file. +	 * CHILD  	 */ -	if (ChangeUser(file->cf_User, 1) < 0) -	    exit(0); -  	/* -	 * run sendmail with mail file as standard input, only if -	 * mail file exists! +	 * Change running state to the user in question  	 */ -	dup2(mailFd, 0); -	dup2(1, 2); -	close(mailFd); +	if (ChangeUser(user) < 0) +	    exit(0); + +#ifdef FEATURE_DEBUG_OPT +	if (DebugOpt) +	    log("\005Child Running %s\n", def_sh); +#endif -	execl(SENDMAIL, SENDMAIL, SENDMAIL_ARGS, NULL, NULL); -	log_err("unable to exec %s %s, user %s, output to sink null", -	    SENDMAIL, -	    SENDMAIL_ARGS, -	    file->cf_User -	); +	execl(def_sh, def_sh, "-c", line->cl_Shell, NULL); +	log("\024unable to exec, user %s cmd %s -c %s\n", user, +	    def_sh, line->cl_Shell);  	exit(0); -    } else if (line->cl_Pid < 0) { -	/* -	 * PARENT, FORK FAILED -	 */ -	log_err("unable to fork, user %s", file->cf_User); -	line->cl_Pid = 0; -    } else { +    } else if (pid < 0) {  	/* -	 * PARENT, FORK OK +	 * FORK FAILED  	 */ +	log("\024couldn't fork, user %s\n", user); +	pid = 0;      } -    close(mailFd); +    line->cl_Pid = pid;  } +#endif /* CONFIG_FEATURE_CROND_CALL_SENDMAIL */ diff --git a/networking/Config.in b/networking/Config.in index 406b99163..0bd17fb63 100644 --- a/networking/Config.in +++ b/networking/Config.in @@ -58,6 +58,13 @@ config CONFIG_FEATURE_HTTPD_BASIC_AUTH  	  Utilizes password settings from /etc/httpd.conf for basic  	  authentication on a per url basis. +config CONFIG_FEATURE_HTTPD_AUTH_MD5 +	bool "  Enable support MD5 crypted password for httpd.conf" +	default n +	depends on CONFIG_FEATURE_HTTPD_BASIC_AUTH +	help +	  Please help my - send patch for set this help message +  if !CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY  config CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP @@ -105,7 +112,7 @@ config CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV  config CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV  	bool "  Enable setting of CGI_varname=value environment vars for CGI" -	default y +	default n  	depends on CONFIG_FEATURE_HTTPD_CGI  	help  	  This option parses POST or GET arguments from a form and diff --git a/networking/Makefile.in b/networking/Makefile.in index 7d0d0b8bc..7748d066b 100644 --- a/networking/Makefile.in +++ b/networking/Makefile.in @@ -53,6 +53,13 @@ NETWORKING-$(CONFIG_WGET)		+= wget.o  libraries-y+=$(NETWORKING_DIR)$(NETWORKING_AR) +needcrypt-y:= +needcrypt-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) := y + +ifeq ($(needcrypt-y),y) +  LIBRARIES += -lcrypt +endif +  $(NETWORKING_DIR)$(NETWORKING_AR): $(patsubst %,$(NETWORKING_DIR)%, $(NETWORKING-y))  	$(AR) -ro $@ $(patsubst %,$(NETWORKING_DIR)%, $(NETWORKING-y)) diff --git a/networking/httpd.c b/networking/httpd.c index d3d88fcb6..d58414b55 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -153,12 +153,14 @@ static const char home[] = "./";  /* Config options, disable this for do very small module */  //#define CONFIG_FEATURE_HTTPD_CGI  //#define CONFIG_FEATURE_HTTPD_BASIC_AUTH +//#define CONFIG_FEATURE_HTTPD_AUTH_MD5  #ifdef HTTPD_STANDALONE  /* standalone, enable all features */  #undef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY  /* unset config option for remove warning as redefined */  #undef CONFIG_FEATURE_HTTPD_BASIC_AUTH +#undef CONFIG_FEATURE_HTTPD_AUTH_MD5  #undef CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV  #undef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR  #undef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV @@ -168,6 +170,7 @@ static const char home[] = "./";  #undef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP  /* enable all features now */  #define CONFIG_FEATURE_HTTPD_BASIC_AUTH +#define CONFIG_FEATURE_HTTPD_AUTH_MD5  #define CONFIG_FEATURE_HTTPD_SET_CGI_VARS_TO_ENV  #define CONFIG_FEATURE_HTTPD_ENCODE_URL_STR  #define CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV @@ -425,11 +428,11 @@ static void parse_conf(const char *path, int flag)      }      while((f = fopen(cf, "r")) == NULL) { -	if(flag != FIRST_PARSE) { +	if(flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) {  	    /* config file not found, no changes to config */  	    return;  	} -	if(config->configFile)      /* if -c option given */ +	if(config->configFile && flag == FIRST_PARSE) /* if -c option given */  	    bb_perror_msg_and_die("%s", cf);  	flag = FIND_FROM_HTTPD_ROOT;  	cf = httpd_conf; @@ -1326,10 +1329,38 @@ static int checkPerm(const char *path, const char *request)  	    if(strncmp(p0, path, l) == 0 &&  			    (l == 1 || path[l] == '/' || path[l] == 0)) {  		/* path match found.  Check request */ + +		/* for check next /path:user:password */ +		prev = p0; +#ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 +		{ +			char *cipher; +			char *pp; +			char *u = strchr(request, ':'); + +			if(u == NULL) { +				/* bad request, ':' required */ +				continue; +			} +			if(strncmp(p, request, u-request) != 0) { +				/* user uncompared */ +				continue; +			} +			pp = strchr(p, ':'); +			if(pp && pp[1] == '$' && pp[2] == '1' && +						 pp[3] == '$' && pp[4]) { +				pp++; +				cipher = pw_encrypt(u+1, pp); +				if (strcmp(cipher, pp) == 0) +					return 1;   /* Ok */ +				/* unauthorized */ +				continue; +			} +		} +#endif  		if (strcmp(p, request) == 0)  		    return 1;   /* Ok */ -		/* unauthorized, but check next /path:user:password */ -		prev = p0; +		/* unauthorized */  	    }  	}      }   /* for */ @@ -1731,7 +1762,12 @@ static const char httpd_opts[]="c:d:h:"  #endif  #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH  				"r:" -#define OPT_INC_2 1 +# ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 +				"m:" +# define OPT_INC_2 2 +# else +# define OPT_INC_2 1 +#endif  #else  #define OPT_INC_2 0  #endif @@ -1740,14 +1776,15 @@ static const char httpd_opts[]="c:d:h:"  #ifdef CONFIG_FEATURE_HTTPD_SETUID  				"u:"  #endif -#endif +#endif /* CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY */  					;  #define OPT_CONFIG_FILE (1<<0)  #define OPT_DECODE_URL  (1<<1)  #define OPT_HOME_HTTPD  (1<<2)  #define OPT_ENCODE_URL  (1<<(2+OPT_INC_1)) -#define OPT_REALM       (1<<(2+OPT_INC_1+OPT_INC_2)) +#define OPT_REALM       (1<<(3+OPT_INC_1)) +#define OPT_MD5         (1<<(4+OPT_INC_1))  #define OPT_PORT        (1<<(3+OPT_INC_1+OPT_INC_2))  #define OPT_DEBUG       (1<<(4+OPT_INC_1+OPT_INC_2))  #define OPT_SETUID      (1<<(5+OPT_INC_1+OPT_INC_2)) @@ -1778,6 +1815,10 @@ int httpd_main(int argc, char *argv[])    long uid = -1;  #endif +#ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 +  const char *pass; +#endif +    config = xcalloc(1, sizeof(*config));  #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH    config->realm = "Web Server Authentication"; @@ -1796,6 +1837,9 @@ int httpd_main(int argc, char *argv[])  #endif  #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH  			, &(config->realm) +# ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 +			, &pass +# endif  #endif  #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY  			, &s_port @@ -1815,6 +1859,12 @@ int httpd_main(int argc, char *argv[])        return 0;    }  #endif +#ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 +  if(opt & OPT_MD5) { +      printf("%s\n", pw_encrypt(pass, "$1$")); +      return 0; +  } +#endif  #ifndef CONFIG_FEATURE_HTTPD_USAGE_FROM_INETD_ONLY      if(opt & OPT_PORT)  	config->port = bb_xgetlarg(s_port, 10, 1, 0xffff); diff --git a/networking/inetd.c b/networking/inetd.c index 33b97ba94..af262c39c 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -806,7 +806,9 @@ inetd_main(int argc, char *argv[])  	struct passwd *pwd;  	struct group *grp = NULL;  	struct sigaction sa; -	int ch, pid; +	int pid; +	unsigned long opt; +	char *sq;  	gid_t gid;  #ifdef INETD_UNSUPPORT_BILTIN @@ -828,14 +830,21 @@ inetd_main(int argc, char *argv[])  	LastArg = environ[-1] + strlen(environ[-1]);  #endif -	while ((ch = getopt(argc, argv, "q:")) != EOF) -		switch(ch) { -		case 'q': +#if defined(__uClinux__) +	opt = bb_getopt_ulflags(argc, argv, "q:f", &sq); +	if (!(opt & 4)) { +	    daemon(0, 0); +	    /* reexec for vfork() do continue parent */ +	    vfork_daemon_rexec(argc, argv, "-f"); +	} +#else +	opt = bb_getopt_ulflags(ac, av, "q:", &sq); +	daemon(0, 0); +#endif /* uClinux */ + +	if(opt & 1) {  			global_queuelen = atoi(optarg);  			if (global_queuelen < 8) global_queuelen=8; -			break; -		default: -			bb_show_usage(); // "[-q len] [conf]"  		}  	argc -= optind;  	argv += optind; @@ -843,7 +852,6 @@ inetd_main(int argc, char *argv[])  	if (argc > 0)  		CONFIG = argv[0]; -	daemon(0, 0);  	openlog(bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);  	{  		FILE *fp; diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c index f537a4bb8..2e187b199 100644 --- a/sysklogd/klogd.c +++ b/sysklogd/klogd.c @@ -150,8 +150,8 @@ extern int klogd_main(int argc, char **argv)  #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)  		if (daemon(0, 1) < 0)  			bb_perror_msg_and_die("daemon"); -#else -		bb_error_msg_and_die("daemon not supported"); +#if defined(__uClinux__) +		vfork_daemon_rexec(argc, argv, "-n");  #endif  	}  	doKlogd(console_log_level); diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 67324116d..c554536c8 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -632,11 +632,12 @@ extern int syslogd_main(int argc, char **argv)  	umask(0); -#if ! defined(__uClinux__)  	if ((doFork == TRUE) && (daemon(0, 1) < 0)) {  		bb_perror_msg_and_die("daemon"); -	} +#if ! defined(__uClinux__) +		vfork_daemon_rexec(argc, argv, "-n");  #endif +	}  	doSyslogd();  	return EXIT_SUCCESS; | 
