From 35e643b39f6cc77b702c714cfa8e70f1e10601a9 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Mon, 28 Jul 2003 07:40:39 +0000 Subject: [PATCH] last_patch95 from vodz: Hi. Last patch have new libbb function vfork_rexec() for can use daemon() to uClinux system. This patched daemons: syslog, klogd, inetd, crond. This not tested! I havn`t this systems. Also. Previous patch for feature request MD5 crypt password for httpd don`t sended to this mailist on 07/15/03 (mailist have Pytom module problem?). The previous patch included, and have testing. --w vodz --- include/libbb.h | 2 + libbb/Makefile.in | 2 +- libbb/vfork_daemon_rexec.c | 27 +++ miscutils/Config.in | 7 + miscutils/crond.c | 451 +++++++++++++++++-------------------- networking/Config.in | 9 +- networking/Makefile.in | 7 + networking/httpd.c | 64 +++++- networking/inetd.c | 24 +- sysklogd/klogd.c | 4 +- sysklogd/syslogd.c | 5 +- 11 files changed, 336 insertions(+), 266 deletions(-) create mode 100644 libbb/vfork_daemon_rexec.c 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 +#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 - ; - } - } -} - +#if defined(FEATURE_DEBUG_OPT) || defined(CONFIG_FEATURE_CROND_CALL_SENDMAIL) /* - set log_level=9 and log messages + write to temp file.. */ - -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); -} - -/* - Original: void - logfd(int fd, const char *ctl, ...) - Updated to: log_error (used by jobs.c) -*/ - -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,9 +901,76 @@ CheckJobs(void) } +#ifdef CONFIG_FEATURE_CROND_CALL_SENDMAIL +static void +ForkJob(const char *user, CronLine *line, int mailFd, + const char *prog, const char *cmd, const char *arg, const char *mailf) +{ + /* + * Fork as the user in question and run program + */ + pid_t pid = fork(); + + line->cl_Pid = pid; + if (pid == 0) { + /* + * CHILD + */ + + /* + * Change running state to the user in question + */ + + if (ChangeUser(user) < 0) + exit(0); + +#ifdef FEATURE_DEBUG_OPT + if (DebugOpt) + log("\005Child Running %s\n", prog); +#endif + + if (mailFd >= 0) { + dup2(mailFd, mailf != NULL); + dup2((mailf ? mailFd : 1), 2); + close(mailFd); + } + 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 (pid < 0) { + /* + * FORK FAILED + */ + log("\024couldn't fork, user %s\n", user); + line->cl_Pid = 0; + if(mailf) + remove(mailf); + } else if(mailf) { + /* + * PARENT, FORK SUCCESS + * + * rename mail-file based on pid of process + */ + char mailFile2[128]; + + snprintf(mailFile2, sizeof(mailFile2), TMPDIR "/cron.%s.%d", + 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 + */ + + if (mailFd >= 0) + close(mailFd); +} static void -RunJob(CronFile *file, CronLine *line) +RunJob(const char *user, CronLine *line) { char mailFile[128]; int mailFd; @@ -956,87 +983,20 @@ RunJob(CronFile *file, CronLine *line) */ snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", - file->cf_User, getpid()); + 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 - ); + fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user, + line->cl_Shell); line->cl_MailPos = lseek(mailFd, 0, 1); - } - - /* - * Fork as the user in question and run program - */ - - if ((line->cl_Pid = fork()) == 0) { - /* - * CHILD, FORK OK - */ - - /* - * Change running state to the user in question - */ - - if (ChangeUser(file->cf_User, 1) < 0) - return; - -#ifdef FEATURE_DEBUG_OPT - if (DebugOpt) - log(5, "Child Running %s\n", line->cl_Shell); -#endif - - /* - * stdin is already /dev/null, setup stdout and stderr - */ - - if (mailFd >= 0) { - dup2(mailFd, 1); - dup2(mailFd, 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); - exit(0); - } else if (line->cl_Pid < 0) { - /* - * PARENT, FORK FAILED - */ - log_err("couldn't fork, user %s\n", file->cf_User); - line->cl_Pid = 0; - remove(mailFile); } else { - /* - * PARENT, FORK SUCCESS - * - * rename mail-file based on pid of process - */ - char mailFile2[128]; - - snprintf(mailFile2, sizeof(mailFile2), TMPDIR "/cron.%s.%d", - file->cf_User, line->cl_Pid); - rename(mailFile, mailFile2); + log("\024unable to create mail file user %s file %s, output to /dev/null\n", + user, mailFile); } - /* - * 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 - */ - - if (mailFd >= 0) - close(mailFd); + ForkJob(user, line, mailFd, def_sh, "-c", line->cl_Shell, mailFile); } /* @@ -1044,7 +1004,7 @@ RunJob(CronFile *file, CronLine *line) */ 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) { + /* + * CHILD */ /* - * change user id - no way in hell security can be compromised - * by the mailing and we already verified the mail file. + * Change running state to the user in question */ - if (ChangeUser(file->cf_User, 1) < 0) + if (ChangeUser(user) < 0) exit(0); - /* - * run sendmail with mail file as standard input, only if - * mail file exists! - */ +#ifdef FEATURE_DEBUG_OPT + if (DebugOpt) + log("\005Child Running %s\n", def_sh); +#endif - dup2(mailFd, 0); - dup2(1, 2); - close(mailFd); - - 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) { + } else if (pid < 0) { /* - * PARENT, FORK FAILED - */ - log_err("unable to fork, user %s", file->cf_User); - line->cl_Pid = 0; - } else { - /* - * 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;