diff --git a/freshclam/freshclam.c b/freshclam/freshclam.c index 8953024c82..fd697b9d50 100644 --- a/freshclam/freshclam.c +++ b/freshclam/freshclam.c @@ -811,26 +811,6 @@ static fc_error_t initialize(struct optstruct *opts) #endif } -#ifdef HAVE_PWD_H - /* Drop database privileges here if we are not planning on daemonizing. If - * we are, we should wait until after we create the PidFile to drop - * privileges. That way, it is owned by root (or whoever started freshclam), - * and no one can change it. */ - if (!optget(opts, "daemon")->enabled) { - /* - * freshclam shouldn't work with root privileges. - * Drop privileges to the DatabaseOwner user, if specified. - * Pass NULL for the log file name, because it hasn't been created yet. - */ - ret = drop_privileges(optget(opts, "DatabaseOwner")->strarg, NULL); - if (ret) { - logg(LOGG_ERROR, "Failed to switch to %s user.\n", optget(opts, "DatabaseOwner")->strarg); - status = FC_ECONFIG; - goto done; - } - } -#endif /* HAVE_PWD_H */ - /* * Initialize libclamav. */ @@ -982,6 +962,7 @@ static fc_error_t initialize(struct optstruct *opts) fcConfig.requestTimeout = optget(opts, "ReceiveTimeout")->numarg; fcConfig.bCompressLocalDatabase = optget(opts, "CompressLocalDatabase")->enabled; + fcConfig.dbOwner = optget(opts, "DatabaseOwner")->strarg; /* * Initialize libfreshclam. @@ -992,6 +973,26 @@ static fc_error_t initialize(struct optstruct *opts) goto done; } +#ifdef HAVE_PWD_H + /* Drop database privileges here (cause of log file creation in /var/log) if we are not planning on daemonizing. If + * we are, we should wait until after we create the PidFile to drop + * privileges. That way, it is owned by root (or whoever started freshclam), + * and no one can change it. */ + if (!optget(opts, "daemon")->enabled) { + /* + * freshclam shouldn't work with root privileges. + * Drop privileges to the DatabaseOwner user, if specified. + * Pass NULL for the log file name, because it hasn't been created yet. + */ + ret = drop_privileges(optget(opts, "DatabaseOwner")->strarg, NULL); + if (ret) { + logg(LOGG_ERROR, "Failed to switch to %s user.\n", optget(opts, "DatabaseOwner")->strarg); + status = FC_ECONFIG; + goto done; + } + } +#endif /* HAVE_PWD_H */ + /* * Set libfreshclam callback functions. */ diff --git a/libfreshclam/libfreshclam.c b/libfreshclam/libfreshclam.c index 400f44694c..e21589baa3 100644 --- a/libfreshclam/libfreshclam.c +++ b/libfreshclam/libfreshclam.c @@ -123,6 +123,71 @@ const char *fc_strerror(fc_error_t fcerror) } } +int fc_upsert_logg_file(fc_config *fcConfig) +{ + if (fcConfig->logFile == NULL) { + return 0; + } + int ret = 0, field_no = 1; + char *current_path, *file_path = cli_safer_strdup(fcConfig->logFile), *token; + FILE *logg_fp = NULL; + token = cli_strtok(file_path, field_no++, PATHSEP); + struct passwd *current_user, *db_owner; +#ifndef _WIN32 + current_user = getpwuid(getuid()); + db_owner = getpwnam(fcConfig->dbOwner); +#endif /* _WIN32 */ + current_path = (char *)malloc(2); + strcpy(current_path, PATHSEP); + STATBUF sb; + while (token != NULL) { + current_path = (char *)realloc(current_path, strlen(current_path) + strlen(token) + 2); + strcat(current_path, token); + free(token); + token = cli_strtok(file_path, field_no++, PATHSEP); + if (token == NULL) { + break; + } + if (LSTAT(current_path, &sb) == -1) { + if (mkdir(current_path, 0755) == -1) { + printf("ERROR: Failed to create required directory %s. Will continue without writing in %s.\n", current_path, fcConfig->logFile); + ret = -1; + goto cleanup; + } +#ifndef _WIN32 + if (current_user->pw_uid != db_owner->pw_uid) { + if (lchown(current_path, db_owner->pw_uid, db_owner->pw_gid) == -1) { + printf("ERROR: Failed to change owner of %s to %s. Will continue without writing in %s.\n", current_path, fcConfig->dbOwner, fcConfig->logFile); + ret = -1; + goto cleanup; + } + } +#endif /* _WIN32 */ + } + strcat(current_path, PATHSEP); + } + if ((logg_fp = fopen(fcConfig->logFile, "at")) == NULL) { + printf("ERROR: Can't open %s in append mode (check permissions!).\n", fcConfig->logFile); + ret = -1; + goto cleanup; + } +#ifndef _WIN32 + lchown(fcConfig->logFile, db_owner->pw_uid, db_owner->pw_gid); +#endif /* _WIN32 */ + +cleanup: + if (token != NULL) { + free(token); + } + free(current_path); + free(file_path); + if (logg_fp != NULL) { + fclose(logg_fp); + } + + return ret; +} + fc_error_t fc_initialize(fc_config *fcConfig) { fc_error_t status = FC_EARG; @@ -157,6 +222,8 @@ fc_error_t fc_initialize(fc_config *fcConfig) logg_rotate = (fcConfig->logFlags & FC_CONFIG_LOG_ROTATE) ? 1 : 0; logg_size = fcConfig->maxLogSize; /* Set a log file if requested, and is not already set */ + fc_upsert_logg_file(fcConfig); + if ((NULL == logg_file) && (NULL != fcConfig->logFile)) { logg_file = cli_safer_strdup(fcConfig->logFile); if (0 != logg(LOGG_INFO_NF, "--------------------------------------\n")) { diff --git a/libfreshclam/libfreshclam.h b/libfreshclam/libfreshclam.h index 25d7293fef..36bfa235c7 100644 --- a/libfreshclam/libfreshclam.h +++ b/libfreshclam/libfreshclam.h @@ -60,6 +60,7 @@ typedef struct fc_config_ { const char *proxyPassword; /**< (optional) Password for proxy server authentication. */ const char *databaseDirectory; /**< Filepath of database directory. */ const char *tempDirectory; /**< Filepath to store temp files. */ + const char *dbOwner; /**< Owner of DB, used when creating log file/folder. */ } fc_config; typedef enum fc_error_tag {