aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2015-10-15 08:27:28 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2015-10-15 08:28:59 +0000
commit9478886233d1c78f702cd06744cda520919af611 (patch)
tree28784f9fe07bf2b9f00a74385c8e51cd68fa8835 /main
parentb27e8afcc7db7ceea1ad5976786f3a8833379da7 (diff)
downloadaports-9478886233d1c78f702cd06744cda520919af611.tar.bz2
aports-9478886233d1c78f702cd06744cda520919af611.tar.xz
main/ca-certificates: replace update-ca-certificates implementation
Use C implementation to avoid Lua dependency. https://github.com/xynopsis/update_ca_cert
Diffstat (limited to 'main')
-rw-r--r--main/ca-certificates/APKBUILD19
-rw-r--r--main/ca-certificates/update-ca.c335
2 files changed, 346 insertions, 8 deletions
diff --git a/main/ca-certificates/APKBUILD b/main/ca-certificates/APKBUILD
index 8c458b62b7..af08b7ca99 100644
--- a/main/ca-certificates/APKBUILD
+++ b/main/ca-certificates/APKBUILD
@@ -7,24 +7,27 @@ _nmu="+nmu${pkgver#*_p}"
[ "$_nmu" = "+nmu${pkgver}" ] && _nmu=""
_ver=${pkgver}
-pkgrel=0
+pkgrel=1
pkgdesc="Common CA certificates PEM files"
url="http://packages.debian.org/sid/ca-certificates"
-arch="noarch"
+arch="all"
license="MPL 2.0 GPL2+"
-depends="run-parts openssl lua5.2 lua5.2-posix"
+depends="openssl"
makedepends="python"
subpackages="$pkgname-doc"
options="!fhs"
triggers="ca-certificates.trigger=/usr/share/ca-certificates:/usr/local/share/ca-certificates:/etc/ssl/certs"
source="http://ftp.no.debian.org/debian/pool/main/c/$pkgname/${pkgname}_${_ver}.tar.xz
- update-ca-certificates
+ update-ca.c
"
_builddir="$srcdir"/$pkgname-$_ver
build () {
cd "$_builddir"
make || return 1
+
+ ${CC:-gcc} ${CFLAGS} -o update-ca-certificates "$srcdir"/update-ca.c \
+ ${LDFLAGS} || return 1
}
package() {
@@ -50,7 +53,7 @@ package() {
# http://bugs.alpinelinux.org/issues/2715
# http://bugs.alpinelinux.org/issues/2846
- install -m755 "$srcdir"/update-ca-certificates "$pkgdir"/usr/sbin \
+ install -m755 update-ca-certificates "$pkgdir"/usr/sbin \
|| return 1
mkdir -p "$pkgdir"/etc/apk/protected_paths.d
@@ -62,8 +65,8 @@ EOF
}
md5sums="717455f13fb31fd014a11a468ea3895d ca-certificates_20150426.tar.xz
-0c2fb9aa695d9d857fecd1c236930016 update-ca-certificates"
+10414777ecc6ee6c542e6389179eaa00 update-ca.c"
sha256sums="37dbaa93ed64cc4ae93ac295f9248fbc741bd51376438cfb1257f17efab5494f ca-certificates_20150426.tar.xz
-b95a80d5881a3ffeea3f36599503a141f9c5a433bc9646d673225658ebc032a1 update-ca-certificates"
+ad8fda22d18ad57a1b8c7e8fb204fc74966c7908bda00e3465ad9cd306ec4df1 update-ca.c"
sha512sums="920dfc512c018c5338bf07b6a6afcb664d9bfba659d4233ca9e87471d5e0ed05de054c96f3d7e6091549aa6deb46106a79f7f982696081f9b2164e18133eb34d ca-certificates_20150426.tar.xz
-ce0e6317af25a5433a4fef28db6afd0ef985089f4a6b9eb13ac1ca454de854ae3de18029fed1e385651317cb237581a38d3792c42f5f30ec12667609d689b4e1 update-ca-certificates"
+32f823236d665fd0bfd9f2afb387527036275047b7003fb82c9fa654e40616e967ed3a1eb2c850844c88efb835c1454112b5b1d10d2c3bc82c85c96563223790 update-ca.c"
diff --git a/main/ca-certificates/update-ca.c b/main/ca-certificates/update-ca.c
new file mode 100644
index 0000000000..4a2f8fc0bf
--- /dev/null
+++ b/main/ca-certificates/update-ca.c
@@ -0,0 +1,335 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libgen.h>
+
+#include <sys/stat.h>
+#include <sys/sendfile.h>
+
+#define CERTSDIR "/usr/share/ca-certificates/"
+#define LOCALCERTSDIR "/usr/local/share/ca-certificates/"
+#define ETCCERTSDIR "/etc/ssl/certs/"
+#define CERTBUNDLE "ca-certificates.crt"
+#define CERTSCONF "/etc/ca-certificates.conf"
+
+static bool str_begins(const char* str, const char* prefix)
+{
+ return !strncmp(str, prefix, strlen(prefix));
+}
+
+/* A string pair */
+struct pair
+{
+ char** first;
+ char** second;
+
+ /* Total size */
+ unsigned size;
+ /* Fill-level */
+ unsigned count;
+};
+
+static void pair_free(struct pair* data)
+{
+ int i = 0;
+ for (i = 0; i < data->size; i++) {
+ free(data->first[i]);
+ free(data->second[i]);
+ }
+ free(data->first);
+ free(data->second);
+ free(data);
+}
+
+static struct pair* pair_alloc(int size)
+{
+ struct pair* d = (struct pair*) malloc(sizeof(struct pair));
+ d->size = size;
+ d->count = 0;
+ d->first = calloc(size, sizeof(char** ));
+ d->second = calloc(size, sizeof(char** ));
+
+ return d;
+}
+
+static const char*
+get_pair(struct pair* data, const char* key, int* pos)
+{
+ int i = 0;
+ for (i = 0; i < data->size; i++) {
+ *pos = i;
+ if (data->second[i] && data->first[i]) {
+ if (str_begins(key, data->second[i]))
+ return data->first[i];
+ else if (str_begins(key, data->first[i]))
+ return data->second[i];
+ }
+ }
+
+ return 0;
+}
+
+static bool
+add_ca_from_pem(struct pair* data, const char* ca, const char* pem)
+{
+ int count = data->count++;
+ if (count >= data->size)
+ return false;
+
+ data->first[count] = strdup(ca);
+ data->second[count] = strdup(pem);
+
+ return true;
+}
+
+static bool
+copyfile(const char* source, int output)
+{
+ int input;
+ if ((input = open(source, O_RDONLY)) == -1)
+ return -1;
+
+ off_t bytes = 0;
+ struct stat fileinfo = {0};
+ fstat(input, &fileinfo);
+ int result = sendfile(output, input, &bytes, fileinfo.st_size);
+
+ close(input);
+
+ return (fileinfo.st_size == result);
+}
+
+typedef void (*proc_path)(const char*, struct pair*, int);
+
+static void proc_localglobaldir(const char* path, struct pair* d, int tmpfile_fd)
+{
+ /* basename() requires we duplicate the string */
+ char* base = strdup(path);
+ char* tmp_file = strdup(basename(base));
+ int base_len = strlen(tmp_file);
+ char* actual_file = 0;
+
+ /* Snip off the .crt suffix*/
+ if (base_len > 4 && strcmp(&tmp_file[base_len - 4], ".crt") == 0)
+ tmp_file[base_len - 4] = 0;
+
+ bool build_string = asprintf(&actual_file, "%s%s%s", "ca-cert-",
+ tmp_file, ".pem") != -1;
+
+ if (base_len > 0 && build_string) {
+ char* s;
+ for (s = actual_file; *s != 0; s++) {
+ switch(*s) {
+ case ',':
+ case ' ':
+ *s = '_';
+ break;
+ case ')':
+ case '(':
+ *s = '=';
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (add_ca_from_pem(d, path, actual_file)) {
+ if (copyfile(path, tmpfile_fd) == -1)
+ printf("Cant copy %s\n", path);
+ } else {
+ printf("Warn! Cannot add: %s\n", path);
+ }
+ } else {
+ printf("Can't open path: %s\n", path);
+ }
+
+ free(base);
+ free(actual_file);
+ free(tmp_file);
+}
+
+static void proc_etccertsdir(const char* path, struct pair* d, int tmpfile_fd)
+{
+ struct stat statbuf;
+
+ if (lstat(path, &statbuf) == -1)
+ return;
+
+ char* fullpath = (char*) malloc(sizeof(char*) * statbuf.st_size + 1);
+ if (readlink(path, fullpath, statbuf.st_size + 1) == -1)
+ return;
+
+ char* base = strdup(path);
+ const char* actual_file = basename(base);
+ int pos = -1;
+ const char* target = get_pair(d, actual_file, &pos);
+
+ if (!target) {
+ /* Symlink exists but is not wanted
+ * Delete it if it points to 'our' directory
+ */
+ if (str_begins(fullpath, CERTSDIR) || str_begins(fullpath, LOCALCERTSDIR))
+ remove(fullpath);
+ } else if (strncmp(fullpath, target, strlen(fullpath)) != 0) {
+ /* Symlink exists but points wrong */
+ if (symlink(target, path) == -1)
+ printf("Warning! Can't link %s -> %s\n", target, path);
+ } else {
+ /* Symlink exists and is ok */
+ memset(d->first[pos], 0, strlen(d->first[pos]));
+ }
+
+ free(base);
+ free(fullpath);
+}
+
+static bool file_readline(const char* file, struct pair* d, int tmpfile_fd)
+{
+ FILE * fp = fopen(file, "r");
+ if (fp == NULL)
+ return false;
+
+ char * line = NULL;
+ size_t len = 0;
+ ssize_t read;
+
+ while ((read = getline(&line, &len, fp)) != -1) {
+ if (str_begins(line, "#") || str_begins(line, "!"))
+ continue;
+
+ char* newline = strstr(line, "\n");
+ if (newline) {
+ line[newline - line] = '\0';
+ }
+
+ char* fullpath = 0;
+ if (asprintf(&fullpath,"%s%s", CERTSDIR, line) != -1) {
+ proc_localglobaldir(fullpath, d, tmpfile_fd);
+ free(fullpath);
+ }
+ }
+
+ fclose(fp);
+ if (line)
+ free(line);
+
+ return true;
+}
+
+typedef enum {
+ FILE_LINK,
+ FILE_REGULAR
+} filetype;
+
+static bool is_filetype(const char* path, filetype file_check)
+{
+ struct stat statbuf;
+
+ if (lstat(path, &statbuf) < 0)
+ return false;
+ switch(file_check) {
+ case FILE_LINK: return S_ISLNK(statbuf.st_mode);
+ case FILE_REGULAR: return S_ISREG(statbuf.st_mode);
+ default: break;
+ }
+
+ return false;
+}
+
+static bool dir_readfiles(struct pair* d, const char* path,
+ filetype allowed_file_type,
+ proc_path path_processor,
+ int tmpfile_fd)
+{
+ DIR *dp = opendir(path);
+ if (!dp)
+ return false;
+
+ struct dirent *dirp;
+ while ((dirp = readdir(dp)) != NULL) {
+ if (str_begins(dirp->d_name, "."))
+ continue;
+
+ int size = strlen(path) + strlen(dirp->d_name);
+ char* fullpath = 0;
+ if (asprintf(&fullpath, "%s%s", path, dirp->d_name) != -1) {
+ if (is_filetype(fullpath, allowed_file_type))
+ path_processor(fullpath, d, tmpfile_fd);
+
+ free(fullpath);
+ }
+ }
+
+ return closedir(dp) == 0;
+}
+
+int main(int a, char **v)
+{
+ struct pair* calinks = pair_alloc(256);
+
+ const char* bundle = "bundleXXXXXX";
+ int etccertslen = strlen(ETCCERTSDIR);
+ char* tmpfile = 0;
+ if (asprintf(&tmpfile, "%s%s", ETCCERTSDIR, bundle) == -1)
+ return 0;
+
+ int fd = mkstemp(tmpfile);
+ if (fd == -1) {
+ printf("Failed to open temporary file %s for ca bundle\n", tmpfile);
+ exit(0);
+ }
+
+ /* Handle global CA certs from config file */
+ file_readline(CERTSCONF, calinks, fd);
+
+ /* Handle local CA certificates */
+ dir_readfiles(calinks, LOCALCERTSDIR, FILE_REGULAR, &proc_localglobaldir, fd);
+
+ /* Update etc cert dir for additions and deletions*/
+ dir_readfiles(calinks, ETCCERTSDIR, FILE_LINK, &proc_etccertsdir, fd);
+
+ int i = 0;
+ for (i = 0; i < calinks->count; i++) {
+ if (!strlen(calinks->first[i]))
+ continue;
+ int file_len = strlen(calinks->second[i]);
+ char* newpath = 0;
+ bool build_str = asprintf(&newpath, "%s%s", ETCCERTSDIR,
+ calinks->second[i]) != -1;
+ if (!build_str || symlink(calinks->first[i], newpath) == -1)
+ printf("Warning! Can't link %s -> %s\n",
+ calinks->first[i], newpath);
+ free(newpath);
+ }
+
+ /* Update hashes and the bundle */
+ if (fd != -1) {
+ close(fd);
+ char* newcertname = 0;
+ if (asprintf(&newcertname, "%s%s", ETCCERTSDIR, CERTBUNDLE) != -1) {
+ rename(tmpfile, newcertname);
+ free(newcertname);
+ }
+ }
+
+ pair_free(calinks);
+ free(tmpfile);
+
+ /* Execute c_rehash */
+ int nullfd = open("/dev/null", O_WRONLY);
+ if (nullfd == -1)
+ return 0;
+
+ if (dup2(nullfd, STDOUT_FILENO) == -1)
+ return 0;
+
+ char* c_rehash_args[] = { "/usr/bin/c_rehash", ETCCERTSDIR, ">", "/dev/null", 0 };
+ execve(c_rehash_args[0], c_rehash_args, NULL);
+
+ return 0;
+}