]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add rsync command execution to download repositories
authordhfelix <daniel.hdz.felix@hotmail.com>
Fri, 14 Dec 2018 22:48:40 +0000 (16:48 -0600)
committerdhfelix <daniel.hdz.felix@hotmail.com>
Fri, 14 Dec 2018 22:48:40 +0000 (16:48 -0600)
First version of the code, when executing the app, if a 4th arg is
detected, the app will not run rsync.

Maybe I need to replace the "system()" call with another function to
execute the "rsync command"

Also needs to read the "rsync command" from a user JSON configuration
file.

src/Makefile.am
src/main.c
src/object/certificate.c
src/rsync/rsync.c [new file with mode: 0644]
src/rsync/rsync.h [new file with mode: 0644]

index 23378d8094436ea623b8dd79b583742d17def3a4..6e6149e986640177dcba54a4558fb3726c9efb1b 100644 (file)
@@ -17,6 +17,8 @@ rpki_validator_SOURCES += sorted_array.h sorted_array.c
 rpki_validator_SOURCES += state.h state.c
 rpki_validator_SOURCES += thread_var.h thread_var.c
 
+rpki_validator_SOURCES += rsync/rsync.h rsync/rsync.c
+
 rpki_validator_SOURCES += asn1/content_info.h asn1/content_info.c
 rpki_validator_SOURCES += asn1/decode.h asn1/decode.c
 rpki_validator_SOURCES += asn1/oid.h asn1/oid.c
index f3442b56fe0e7e405a7263b1016bbc16881e701e..3d44138b225cd2c01bc7df238d43fd5186c6a9d1 100644 (file)
@@ -8,6 +8,7 @@
 #include "thread_var.h"
 #include "object/certificate.h"
 #include "object/tal.h"
+#include "rsync/rsync.h"
 
 /**
  * Registers the RPKI-specific OIDs in the SSL library.
@@ -42,6 +43,10 @@ handle_tal_uri(char const *uri)
        if (error)
                return error;
 
+       error = download_files(uri);
+       if (error)
+               return error;
+
        error = validation_create(&state, cert_file);
        if (error)
                goto end1;
@@ -72,6 +77,7 @@ main(int argc, char **argv)
 {
        struct tal *tal;
        int error;
+       bool is_rsync_active = true;
 
        print_stack_trace_on_segfault();
 
@@ -80,6 +86,13 @@ main(int argc, char **argv)
                return -EINVAL;
        }
 
+       if (argc >= 4)
+               is_rsync_active = false;
+
+       error = rsync_init(is_rsync_active);
+       if (error)
+               return error;
+
        add_rpki_oids();
        thvar_init();
        fnstack_store();
@@ -94,5 +107,6 @@ main(int argc, char **argv)
        error = foreach_uri(tal, handle_tal_uri);
 
        tal_destroy(tal);
+       rsync_destroy();
        return error;
 }
index ed997f8a0905c0e338828b079ed1e57db19cc67a..d667175481344a42938df770858ffd715bc5f741 100644 (file)
@@ -9,6 +9,7 @@
 #include "manifest.h"
 #include "thread_var.h"
 #include "asn1/decode.h"
+#include "../rsync/rsync.h"
 
 /*
  * The X509V3_EXT_METHOD that references NID_sinfo_access uses the AIA item.
@@ -381,24 +382,33 @@ certificate_get_resources(X509 *cert, struct resources *resources)
        return error;
 }
 
-int certificate_traverse(X509 *cert)
+static int
+_certificate_traverse(X509 *cert, SIGNATURE_INFO_ACCESS *sia, int sia_len)
 {
-       SIGNATURE_INFO_ACCESS *sia;
        ACCESS_DESCRIPTION *ad;
+       ACCESS_DESCRIPTION *list[sia_len];
        char *uri;
-       int i;
        int error;
+       int i;
+       int count;
 
-       sia = X509_get_ext_d2i(cert, NID_sinfo_access, NULL, NULL);
-       if (sia == NULL) {
-               pr_err("Certificate lacks a Subject Information Access extension.");
-               return -ESRCH;
-       }
-
-       error = 0;
-       for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) {
+       for (i = 0, count = 0; i < sia_len; i++) {
                ad = sk_ACCESS_DESCRIPTION_value(sia, i);
+               if (OBJ_obj2nid(ad->method) == NID_caRepository) {
+                       error = gn2uri(ad->location, (char const **)&uri);
+                       if (error)
+                               goto end;
+                       error = download_files(uri);
+                       if (error)
+                               goto end;
+               } else {
+                       list[count] = ad;
+                       count++;
+               }
+       }
 
+       for (i = 0; i < count; i++) {
+               ad = list[i];
                if (OBJ_obj2nid(ad->method) == NID_rpkiManifest) {
                        error = gn_g2l(ad->location, &uri);
                        if (error)
@@ -411,6 +421,24 @@ int certificate_traverse(X509 *cert)
        }
 
 end:
+       return error;
+}
+
+int certificate_traverse(X509 *cert)
+{
+       SIGNATURE_INFO_ACCESS *sia;
+       int error;
+
+
+       sia = X509_get_ext_d2i(cert, NID_sinfo_access, NULL, NULL);
+       if (sia == NULL) {
+               pr_err("Certificate lacks a Subject Information Access extension.");
+               return -ESRCH;
+       }
+
+       error = _certificate_traverse(cert, sia, sk_ACCESS_DESCRIPTION_num(sia));
+
        AUTHORITY_INFO_ACCESS_free(sia);
        return error;
 }
+
diff --git a/src/rsync/rsync.c b/src/rsync/rsync.c
new file mode 100644 (file)
index 0000000..c5e4119
--- /dev/null
@@ -0,0 +1,433 @@
+#include "rsync.h"
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common.h"
+
+struct uri {
+       char *string;
+       size_t len;
+       SLIST_ENTRY(uri) next;
+};
+
+SLIST_HEAD(uri_list, uri);
+
+static struct uri_list *rsync_uris;
+static bool execute_rsync = true;
+
+//static const char *rsync_command[] = {"rsync", "--recursive", "--delete", "--times", NULL};
+
+static int create_dir_recursive(char *);
+static int create_dir(char *);
+static int do_rsync(char const *);
+static int get_dest_path(char const *, char **);
+static bool is_file(char const *);
+static bool dir_exist(char *);
+
+int
+rsync_init(bool is_rsync_active)
+{
+       // TODO remove the next 2 lines
+       if (!is_rsync_active) {
+               execute_rsync = is_rsync_active;
+               return 0;
+       }
+
+       rsync_uris = malloc(sizeof(struct uri_list));
+       if (!rsync_uris)
+               return -ENOMEM;
+
+       SLIST_INIT(rsync_uris);
+       return 0;
+}
+
+void
+rsync_destroy()
+{
+       struct uri *uri;
+
+       // TODO remove the next 2 lines
+       if (!execute_rsync)
+               return;
+
+       while (!SLIST_EMPTY(rsync_uris)) {
+               uri = SLIST_FIRST(rsync_uris);
+               SLIST_REMOVE_HEAD(rsync_uris, next);
+               free(uri->string);
+               free(uri);
+       }
+
+       free(rsync_uris);
+}
+
+static int
+do_rsync(char const *rsync_uri)
+{
+       int error;
+       char *command;
+       char *dest;
+       char const *rsync_command = "rsync --recursive --delete --times --contimeout=20 "; /* space char at end*/
+
+       error = get_dest_path(rsync_uri, &dest);
+       if (error)
+               return error;
+
+       command = malloc(strlen(rsync_command) + 1 + strlen(rsync_uri) + 1 + strlen(dest) + 1);
+       if (command == NULL)
+               return -ENOMEM;
+
+       strcpy(command, rsync_command);
+       strcat(command, rsync_uri);
+       strcat(command, " ");
+       strcat(command, dest);
+
+       free(dest);
+
+       printf("(%s) command = %s \n", __func__, command);
+
+       error = system(command);
+       if (error) {
+               printf("result rsync %d\n", error);
+               perror("rsync");
+       }
+       free(command);
+
+       return error;
+}
+
+static int
+get_dest_path(char const *rsync_uri, char **result)
+{
+       char *local_uri, *temp_str;
+       unsigned int result_size;
+       int error;
+       error = uri_g2l(rsync_uri, &local_uri);
+       if (error)
+               return error;
+
+       if (!is_file(local_uri)) {
+               *result = local_uri;
+               return 0;
+       }
+
+       temp_str = strrchr(local_uri, '/');
+       if (temp_str == NULL) {
+               // TODO warning msg
+               return -EINVAL;
+       }
+       result_size = temp_str - local_uri + 1; /* add slash (+1) */
+
+       temp_str = malloc(result_size + 1); /* null char (+1) */
+       if (temp_str == NULL) {
+               return -ENOMEM;
+       }
+       temp_str[result_size] = '\0'; /*Set null char*/
+       strncpy(temp_str, local_uri, result_size);
+       free(local_uri);
+
+       *result = temp_str;
+       return 0;
+}
+
+//static int
+//do_rsync(char *rsync_uri)
+//{
+//     int temp, result;
+//
+//     char *temp_char;
+//     char *rsync_command[] = {"rsync", "--recursive", "--delete", "--times", NULL, NULL, NULL};
+//     char *src = "rsync://rpki.afrinic.net/repository/AfriNIC.cer";
+//     char *dest = "/home/dhf/Desktop/rpkitest/rpki.afrinic.net/repository/";
+//
+//     rsync_command[4] = src;
+//     rsync_command[5] = dest;
+//     temp = 0;
+//     while (temp < 7) {
+//             temp_char = rsync_command[temp];
+//             printf("[%d] ", temp);
+//             if (temp_char == NULL) {
+//                     printf("NULL\n");
+//             } else {
+//                     printf("%s\n", temp_char);
+//             }
+//             temp++;
+//     }
+//     printf("pre execv \n");
+////   result = execve(rsync_command[0], rsync_command, NULL);
+//
+//     result = system("rsync --recursive --delete --times rsync://rpki.afrinic.net/repository/AfriNIC.cer /home/dhf/Desktop/rpkitest/rpki.afrinic.net/repository/");
+////   printf("result execv %d\n", result);
+//     printf("result rsync %d\n", result);
+//     perror("rsync");
+//     return 0;
+//}
+
+static bool
+rsync_uri_prefix_equals(struct uri *rsync_uri, char const *new_uri)
+{
+       size_t uri_len;
+       uri_len = strlen(new_uri);
+
+       if (rsync_uri->len > uri_len)
+               return false;
+
+       return !strncasecmp(rsync_uri->string, new_uri, rsync_uri->len);
+}
+
+static bool
+is_uri_in_list(char const *rsync_uri)
+{
+       struct uri *cursor;
+       bool found;
+
+       if (SLIST_EMPTY(rsync_uris)) {
+               return false;
+       }
+
+       found = false;
+       SLIST_FOREACH(cursor, rsync_uris, next) {
+               if (rsync_uri_prefix_equals(cursor, rsync_uri)) {
+                       found = true;
+                       break;
+               }
+       }
+
+       return found;
+}
+
+static int
+add_uri_to_list(char const *rsync_uri_path)
+{
+       struct uri *rsync_uri;
+       size_t urilen;
+       rsync_uri = malloc(sizeof(struct uri));
+       if (rsync_uri == NULL) {
+               warnx("Out of memory");
+               return -ENOMEM;
+       }
+       urilen = strlen(rsync_uri_path);
+
+       rsync_uri->string = malloc(urilen + 1);
+       if (!rsync_uri->string) {
+               free(rsync_uri);
+               warnx("Out of memory");
+               return -ENOMEM;
+       }
+
+       strcpy(rsync_uri->string, rsync_uri_path);
+       rsync_uri->len = urilen;
+       SLIST_INSERT_HEAD(rsync_uris, rsync_uri, next);
+
+       return 0;
+}
+
+static int
+short_uri(char const *rsync_uri, char **result)
+{
+       char const *const PREFIX = "rsync://";
+       char const *tmp;
+       char *short_uri;
+       size_t result_len;
+       size_t prefix_len;
+
+       prefix_len = strlen(PREFIX);
+
+       if (strncmp(PREFIX, rsync_uri, prefix_len) != 0) {
+//             pr_err("Global URI %s does not begin with '%s'.", rsync_uri,
+//                 PREFIX);
+               return -EINVAL;
+       }
+
+       do {
+               tmp = rsync_uri + prefix_len;
+               tmp = strchr(tmp, '/');
+
+               if (tmp == NULL) {
+                       result_len = strlen(rsync_uri);
+                       break;
+               }
+
+               tmp = tmp + 1;
+               tmp = strchr(tmp, '/');
+
+               if (tmp != NULL)
+                       result_len = strlen(rsync_uri) - strlen(tmp);
+               else
+                       result_len = strlen(rsync_uri);
+
+       } while (0);
+
+       short_uri = malloc(result_len + 1 + 1); /* slash + null chara */
+       if (!short_uri)
+               return -ENOMEM;
+
+       strncpy(short_uri, rsync_uri, result_len);
+       short_uri[result_len] = '/';
+       short_uri[result_len + 1] = '\0';
+
+       *result = short_uri;
+       return 0;
+}
+
+int
+download_files(char const *rsync_uri)
+{
+       int error;
+       char *rsync_uri_path, *localuri;
+
+       // TODO remove the next 2 lines
+       if (!execute_rsync)
+               return 0;
+
+       if (is_uri_in_list(rsync_uri)){
+               printf("(%s) ON LIST: %s\n", __func__, rsync_uri);
+               error = 0;
+               goto end;
+       } else {
+               printf("(%s) DOWNLOAD: %s\n",__func__,  rsync_uri);
+       }
+
+       error = short_uri(rsync_uri, &rsync_uri_path);
+       if (error)
+               return error;
+
+       error = uri_g2l(rsync_uri_path, &localuri);
+       if (error)
+               goto free_uri_path;
+
+       error = create_dir_recursive(localuri);
+       free(localuri);
+       if (error)
+               goto free_uri_path;
+
+       error = do_rsync(rsync_uri_path);
+       if (error)
+               goto free_uri_path;
+
+       error = add_uri_to_list(rsync_uri_path);
+
+free_uri_path:
+       free(rsync_uri_path);
+end:
+       return error;
+
+}
+
+
+static int
+create_dir_recursive(char *localuri)
+{
+       char *temp_luri;
+       char path[PATH_MAX];
+       char *slash;
+       size_t localuri_len;
+       size_t repository_len;
+       unsigned int offset;
+
+       if (dir_exist(localuri))
+               return 0;
+
+       localuri_len = strlen(localuri);
+       repository_len = strlen(repository);
+       temp_luri = localuri + repository_len ;
+
+       strcpy(path, repository);
+       offset = repository_len;
+
+
+       slash = strchr(temp_luri, '/');
+       while (slash != NULL) {
+               if (slash == temp_luri) {
+                       temp_luri++;
+                       localuri_len--;
+                       slash = strchr(temp_luri, '/');
+                       continue;
+               }
+               strcpy(path + offset, "/");
+               offset += 1;
+               strncpy(path + offset, temp_luri, slash - temp_luri);
+               offset += slash - temp_luri;
+               if (offset > localuri_len) {
+                       break;
+               }
+               path[offset] = '\0';
+               if (create_dir(path) == -1) {
+                       perror("Error while creating Dir");
+                       return -1;
+               }
+               temp_luri += slash - temp_luri + 1;
+               slash = strchr(temp_luri, '/');
+       }
+
+       if (offset < localuri_len) {
+               strcpy(path + offset, "/");
+               offset += 1;
+               strcpy(path + offset, temp_luri);
+               offset = localuri + localuri_len - temp_luri + offset + 1;
+               path[offset] = '\0';
+       }
+
+       if (create_dir(path) == -1) {
+               perror("Error while creating Dir");
+               return -1;
+       }
+       return 0;
+
+}
+
+static bool
+is_file(char const *path)
+{
+       if (file_has_extension(path, "cer"))
+               return true;
+       if (file_has_extension(path, "gbr"))
+               return true;
+       if (file_has_extension(path, "mft"))
+               return true;
+
+       return false;
+}
+
+static bool
+dir_exist(char *path)
+{
+       int error;
+       struct stat _stat;
+       error = stat(path, &_stat);
+       if (error == -1)
+               return false; /* a dir or file not exist*/
+
+       return true;
+}
+
+static int
+create_dir(char *path)
+{
+       struct stat _stat;
+       int error;
+       mode_t mode = 0777;
+
+       if (is_file(path))
+               return 0;
+
+       error = stat(path, &_stat);
+       if (error != -1) {
+               /* a dir or file exist*/
+               return 0;
+       }
+
+       if (errno != ENOENT) {
+               perror("stat");
+               return -1; /* another error occurs*/
+       }
+
+       error = mkdir(path, mode);
+       return error;
+}
diff --git a/src/rsync/rsync.h b/src/rsync/rsync.h
new file mode 100644 (file)
index 0000000..3287ebe
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SRC_RSYNC_RSYNC_H_
+#define SRC_RSYNC_RSYNC_H_
+
+#include <stdbool.h>
+
+int download_files(const char *);
+int rsync_init(bool);
+void rsync_destroy();
+
+
+#endif /* SRC_RSYNC_RSYNC_H_ */