/*++
/* NAME
/* nbdb_process 3
/* SUMMARY
/* Non-Berkeley-DB migration service
/* SYNOPSIS
/* #include <nbdb_process.h>
/*
/* int nbdb_process(
/* const char *legacy_type,
/* const char *source_path,
/* VSTRING *why)
/* DESCRIPTION
/* nbdb_process() integrates the safety policy and content policy,
/* and calls spawn_command() to generate an indexed file for
/* $non_legacy_type:$source_path.
/*
/* The result value is NBDB_MIGR_OK (success) or NBDB_MIGR_ERROR
/* (failure).
/*
/* Arguments:
/* .IP new_type
/* A non-legacy database type.
/* .P source_path
/* The pathname for the source text file (no database suffix).
/* .IP why
/* Storage for descriptive text in case of error.
/* SEE ALSO
/* nbdb_safe(3), safety policy
/* nbdb_sniffer(3), content policy
/* nbdb_process_test(1t), unit test
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* porcupine.org
/*--*/
/*
* System library .
*/
#include <sys_defs.h>
#include <libgen.h> /* dirname() */
/*
* Utility library .
*/
#include <attr.h>
#include <msg.h>
#include <spawn_command.h>
#include <vstring.h>
#include <wrap_stat.h>
/*
* Global library .
*/
#include <allowed_prefix.h>
#include <mail_params.h>
#include <nbdb_util.h>
/*
* Application - specific .
*/
#include <nbdb_reindexd.h>
#include <nbdb_safe.h>
#include <nbdb_sniffer.h>
#include <nbdb_index_as.h>
#include <nbdb_process.h>
#define STR(x) vstring_str(x)
/* nbdb_process - main processing flow */
int nbdb_process(const char *leg_type, const char *source_path,
VSTRING *why)
{
const char *new_type;
struct stat source_st;
static VSTRING *new_idx_path;
struct stat new_idx_st;
static VSTRING *leg_idx_path;
struct stat leg_idx_st;
static VSTRING *parent_dir_buf;
struct stat parent_dir_st;
char *parent_dir;
const char *new_suffix;
const char *index_cmd;
int status;
if (new_idx_path == 0 ) {
new_idx_path = vstring_alloc(100 );
leg_idx_path = vstring_alloc(100 );
parent_dir_buf = vstring_alloc(100 );
}
/*
* First things first .
*/
if (nbdb_level < NBDB_LEV_CODE_REINDEX) {
vstring_sprintf(why, "the %s service is disabled" , var_servname);
return (NBDB_STAT_ERROR);
}
/*
* nbdb_map_leg_type ( ) will allow only mapping from an expected Berkeley
* DB type to an expected non - Berkeley - DB type .
*/
if ((new_type = nbdb_map_leg_type(leg_type, source_path,
(const DICT_OPEN_INFO **) 0 , why)) == 0 ) {
return (NBDB_STAT_ERROR);
}
/*
* Look up the non - legacy pathname suffix and build the pathname that
* needs to be created . If no suffix exists then the client is in error .
*/
if ((new_suffix = nbdb_find_non_leg_suffix(new_type)) == 0 ) {
vstring_sprintf(why, "non-Berkeley-DB type '%s' has no known suffix" ,
new_type);
return (NBDB_STAT_ERROR);
}
vstring_sprintf(new_idx_path, "%s%s" , source_path, new_suffix);
/*
* If the target indexed pathname already exists , then do nothing . All
* indexing requests are handled sequentially ( to avoid collisions ) , and
* the client may have connected to this service before the file was
* indexed .
*/
if (stat (STR(new_idx_path), &new_idx_st) == 0 && new_idx_st.st_size > 0 ) {
msg_info("target file '%s' already exists, skipping this request" ,
STR(new_idx_path));
return (NBDB_STAT_OK);
}
/*
* Require that the legacy indexed file exists . We need this to determine
* the owner ' s ( uid , gid ) to run the postmap or postalias command with .
*/
vstring_sprintf(leg_idx_path, "%s%s" , source_path, NBDB_LEGACY_SUFFIX);
if (stat (STR(leg_idx_path), &leg_idx_st) < 0 ) {
vstring_sprintf(why, "look up status for legacy indexed file '%s': %m" ,
STR(leg_idx_path));
return (NBDB_STAT_ERROR);
}
/*
* Require that the source path exists . We need it as input for indexing ,
* and will reject the request if the source has unsafe permissions for
* the uid that we would run postmap or postalias with .
*/
if (stat (source_path, &source_st) < 0 ) {
vstring_sprintf(why, "look up status for source file '%s': %m" ,
source_path);
return (NBDB_STAT_ERROR);
}
/*
* Require that the parent directory exists . We will reject the request
* if the directory has unsafe permissions for the uid that we would run
* postmap or postalias with .
*/
vstring_strcpy(parent_dir_buf, source_path);
parent_dir = dirname(STR(parent_dir_buf));
if (stat (parent_dir, &parent_dir_st) < 0 ) {
vstring_sprintf(why, "look up status for parent directory '%s': %m" ,
parent_dir);
return (NBDB_STAT_ERROR);
}
/*
* Should we run postmap or postalias ? Open the source file with the same
* ( uid , gid ) as the postmap or postalias commands would , so that we can
* detect permission errors quickly .
*
* Note : we do this before the file allowlist / owner / permission safety
* checks , so that we can log the concrete postmap or postalias command
* if a safety check fails .
*/
if ((index_cmd = nbdb_get_index_cmd_as(source_path, leg_idx_st.st_uid,
leg_idx_st.st_gid, why)) == 0 )
return (NBDB_STAT_ERROR);
/*
* Allow indexing as the legacy indexed file owner if it is considered
* " safe " .
*/
if (!nbdb_safe_to_index_as_legacy_index_owner(source_path, &source_st,
STR(leg_idx_path), &leg_idx_st,
parent_dir, &parent_dir_st, why)) {
status = NBDB_STAT_ERROR;
}
/*
* Finally !
*/
else {
status = nbdb_index_as(index_cmd, new_type, source_path,
leg_idx_st.st_uid, leg_idx_st.st_gid, why);
if (status != NBDB_STAT_OK)
/* Don't leave behind a broken indexed file. */
(void ) unlink(STR(new_idx_path));
}
/*
* If the command failed , or was not safe to execute automatically , give
* the user the concrete command so that they could run it by hand .
*/
if (status == NBDB_STAT_OK) {
msg_info("successfully executed '%s %s:%s' as uid %d" ,
index_cmd, new_type, source_path, leg_idx_st.st_uid);
} else {
vstring_sprintf_prepend(why, "could not execute command '%s %s:%s': " ,
index_cmd, new_type, source_path);
vstring_strcat(why,
"; alternatively, execute the failed command by hand" );
}
return (status);
}
Messung V0.5 in Prozent C=86 H=98 G=91
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland