mirror of
https://github.com/nmap/nmap.git
synced 2025-12-23 07:59:03 +00:00
Check a metadata.conf file for channel expiration.
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "nbase.h"
|
#include "nbase.h"
|
||||||
@@ -496,6 +497,17 @@ static struct {
|
|||||||
char *password;
|
char *password;
|
||||||
} options;
|
} options;
|
||||||
|
|
||||||
|
struct metadata {
|
||||||
|
int is_expired;
|
||||||
|
time_t expiry_date;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void metadata_init(struct metadata *metadata)
|
||||||
|
{
|
||||||
|
metadata->is_expired = 0;
|
||||||
|
metadata->expiry_date = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void init_options(void)
|
static void init_options(void)
|
||||||
{
|
{
|
||||||
options.verbose = 1;
|
options.verbose = 1;
|
||||||
@@ -578,6 +590,70 @@ static int read_config_file(const char *conf_filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_date(const char *s, time_t *t)
|
||||||
|
{
|
||||||
|
struct tm tm = {0};
|
||||||
|
|
||||||
|
if (strptime(s, "%Y-%d-%m", &tm) == NULL)
|
||||||
|
return -1;
|
||||||
|
*t = mktime(&tm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int date_is_after(time_t t, time_t now)
|
||||||
|
{
|
||||||
|
return difftime(t, now) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_metadata_file(const char *metadata_filename, struct metadata *metadata)
|
||||||
|
{
|
||||||
|
struct config_parser cp;
|
||||||
|
struct config_entry entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (options.verbose)
|
||||||
|
printf("Trying to open metadata file %s.\n", metadata_filename);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (config_parser_open(metadata_filename, &cp) == -1) {
|
||||||
|
/* A missing file is not an error for metadata. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ret = config_parser_next(&cp, &entry)) > 0) {
|
||||||
|
if (streq(entry.key, "expired")) {
|
||||||
|
if (parse_date(entry.value, &metadata->expiry_date) == -1) {
|
||||||
|
fprintf(stderr, "Warning: %s:%lu: can't parse date \"%s\".\n",
|
||||||
|
metadata_filename, cp.lineno, entry.value);
|
||||||
|
} else {
|
||||||
|
if (date_is_after(metadata->expiry_date, time(NULL)))
|
||||||
|
metadata->is_expired = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Warning: %s:%lu: unknown key \"%s\".\n",
|
||||||
|
metadata_filename, cp.lineno, entry.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
config_entry_free(&entry);
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
fprintf(stderr, "Parse error on line %lu of %s.\n",
|
||||||
|
cp.lineno, metadata_filename);
|
||||||
|
config_parser_close(&cp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (config_parser_close(&cp) == -1) {
|
||||||
|
if (options.verbose)
|
||||||
|
printf("Failed to close %s: %s.\n", metadata_filename, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void usage(FILE *fp)
|
static void usage(FILE *fp)
|
||||||
{
|
{
|
||||||
@@ -599,10 +675,11 @@ static void usage_error(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int try_channels(const char *channels[], unsigned int num_channels);
|
static const char *try_channels(const char *channels[], unsigned int num_channels);
|
||||||
static int stage_and_install(const char *channel);
|
static int stage_and_install(const char *channel);
|
||||||
static int stage_channel(const char *channel, const char *staging_dir);
|
static int stage_channel(const char *channel, const char *staging_dir);
|
||||||
static int install(const char *staging_dir, const char *install_dir);
|
static int install(const char *staging_dir, const char *install_dir);
|
||||||
|
static int channel_is_expired(const char *channel, time_t *expiry_date);
|
||||||
|
|
||||||
static void summarize_options(void)
|
static void summarize_options(void)
|
||||||
{
|
{
|
||||||
@@ -624,6 +701,8 @@ const struct option LONG_OPTIONS[] = {
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt, longoptidx;
|
int opt, longoptidx;
|
||||||
|
const char *successful_channel;
|
||||||
|
time_t expiry_date;
|
||||||
|
|
||||||
internal_assert(argc > 0);
|
internal_assert(argc > 0);
|
||||||
program_name = argv[0];
|
program_name = argv[0];
|
||||||
@@ -660,10 +739,19 @@ int main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try_channels(options.channels, options.num_channels) == 0)
|
successful_channel = try_channels(options.channels, options.num_channels);
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (options.username == NULL) {
|
if (successful_channel != NULL && channel_is_expired(successful_channel, &expiry_date)) {
|
||||||
|
fprintf(stderr, "\
|
||||||
|
\n\
|
||||||
|
Channel is expired: %s\n\
|
||||||
|
\n\
|
||||||
|
The channel %s is expired and will not receive any more updates.\n\
|
||||||
|
Go to http://nmap.org/download.html to get a newer Nmap release.\n\
|
||||||
|
", successful_channel, successful_channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (successful_channel == NULL && options.username == NULL) {
|
||||||
fprintf(stderr, "\
|
fprintf(stderr, "\
|
||||||
\n\
|
\n\
|
||||||
Could not stage any channels and don't have authentication credentials.\n\
|
Could not stage any channels and don't have authentication credentials.\n\
|
||||||
@@ -674,20 +762,23 @@ Edit the file %s and enter your username and password. For example:\n\
|
|||||||
", options.conf_filename);
|
", options.conf_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
if (successful_channel != NULL)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int try_channels(const char *channels[], unsigned int num_channels)
|
static const char *try_channels(const char *channels[], unsigned int num_channels)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < num_channels; i++) {
|
for (i = 0; i < num_channels; i++) {
|
||||||
if (stage_and_install(channels[i]) == 0)
|
if (stage_and_install(channels[i]) == 0)
|
||||||
return 0;
|
return channels[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -798,6 +889,28 @@ static int stage_channel(const char *channel, const char *staging_dir)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int channel_is_expired(const char *channel, time_t *expiry_date)
|
||||||
|
{
|
||||||
|
char *metadata_filename;
|
||||||
|
struct metadata metadata;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
metadata_init(&metadata);
|
||||||
|
|
||||||
|
metadata_filename = path_join(options.staging_dir, channel, "metadata.conf", NULL);
|
||||||
|
rc = read_metadata_file(metadata_filename, &metadata);
|
||||||
|
if (rc == -1) {
|
||||||
|
fprintf(stderr, "Can't read config file %s.\n", metadata_filename);
|
||||||
|
free(metadata_filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free(metadata_filename);
|
||||||
|
|
||||||
|
*expiry_date = metadata.expiry_date;
|
||||||
|
|
||||||
|
return metadata.is_expired;
|
||||||
|
}
|
||||||
|
|
||||||
static int copy_tree(const char *from_dirname, const char *to_dirname);
|
static int copy_tree(const char *from_dirname, const char *to_dirname);
|
||||||
static int rename_file(const char *from_filename, const char *to_filename);
|
static int rename_file(const char *from_filename, const char *to_filename);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user