diff options
Diffstat (limited to 'main/openssl/0007-reimplement-c_rehash-in-C.patch')
-rw-r--r-- | main/openssl/0007-reimplement-c_rehash-in-C.patch | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/main/openssl/0007-reimplement-c_rehash-in-C.patch b/main/openssl/0007-reimplement-c_rehash-in-C.patch new file mode 100644 index 0000000000..eee75d14f5 --- /dev/null +++ b/main/openssl/0007-reimplement-c_rehash-in-C.patch @@ -0,0 +1,447 @@ +From f9044ad2a216f984481645671ccc30a043849fb1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Thu, 5 Feb 2015 09:11:27 +0200 +Subject: [PATCH] reimplement c_rehash in C + +--- + apps/Makefile | 4 +- + apps/c_rehash.c | 383 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + tools/Makefile | 3 +- + 3 files changed, 386 insertions(+), 4 deletions(-) + create mode 100644 apps/c_rehash.c + +diff --git a/apps/Makefile b/apps/Makefile +index 72657ea..3aa03e0 100644 +--- a/apps/Makefile ++++ b/apps/Makefile +@@ -36,7 +36,7 @@ SCRIPTS=CA.sh CA.pl tsget + EXE= $(PROGRAM)$(EXE_EXT) + + E_EXE= verify asn1pars req dgst dh dhparam enc passwd gendh errstr \ +- ca crl rsa rsautl dsa dsaparam ec ecparam \ ++ ca crl c_rehash rsa rsautl dsa dsaparam ec ecparam \ + x509 genrsa gendsa genpkey s_server s_client speed \ + s_time version pkcs7 cms crl2pkcs7 sess_id ciphers nseq pkcs12 \ + pkcs8 pkey pkeyparam pkeyutl spkac smime rand engine ocsp prime ts srp +@@ -51,7 +51,7 @@ RAND_OBJ=app_rand.o + RAND_SRC=app_rand.c + + E_OBJ= verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o \ +- ca.o pkcs7.o crl2p7.o crl.o \ ++ ca.o pkcs7.o crl2p7.o crl.o c_rehash.o \ + rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o \ + x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o \ + s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \ +diff --git a/apps/c_rehash.c b/apps/c_rehash.c +new file mode 100644 +index 0000000..e8d0b86 +--- /dev/null ++++ b/apps/c_rehash.c +@@ -0,0 +1,383 @@ ++/* c_rehash.c - Create hash symlinks for certificates ++ * C implementation based on the original Perl and shell versions ++ * ++ * Copyright (c) 2013-2014 Timo Teräs <timo.teras@iki.fi> ++ * All rights reserved. ++ * ++ * This software is licensed under the MIT License. ++ * Full license available at: http://opensource.org/licenses/MIT ++ */ ++ ++#include <stdio.h> ++#include <limits.h> ++#include <string.h> ++#include <unistd.h> ++#include <dirent.h> ++#include <sys/stat.h> ++ ++#include <openssl/evp.h> ++#include <openssl/pem.h> ++#include <openssl/x509.h> ++ ++#include "apps.h" ++ ++#undef PROG ++#define PROG c_rehash_main ++ ++ ++#define MAX_COLLISIONS 256 ++#define countof(x) (sizeof(x) / sizeof(x[0])) ++ ++#if 0 ++#define DEBUG(args...) fprintf(stderr, args) ++#else ++#define DEBUG(args...) ++#endif ++ ++struct entry_info { ++ struct entry_info *next; ++ char *filename; ++ unsigned short old_id; ++ unsigned char need_symlink; ++ unsigned char digest[EVP_MAX_MD_SIZE]; ++}; ++ ++struct bucket_info { ++ struct bucket_info *next; ++ struct entry_info *first_entry, *last_entry; ++ unsigned int hash; ++ unsigned short type; ++ unsigned short num_needed; ++}; ++ ++enum Type { ++ TYPE_CERT = 0, ++ TYPE_CRL ++}; ++ ++static const char *symlink_extensions[] = { "", "r" }; ++static const char *file_extensions[] = { "pem", "crt", "cer", "crl" }; ++ ++static int evpmdsize; ++static const EVP_MD *evpmd; ++ ++static int do_hash_new = 1; ++static int do_hash_old = 0; ++static int do_remove_links = 1; ++static int do_verbose = 0; ++ ++static struct bucket_info *hash_table[257]; ++ ++static void bit_set(unsigned char *set, unsigned bit) ++{ ++ set[bit / 8] |= 1 << (bit % 8); ++} ++ ++static int bit_isset(unsigned char *set, unsigned bit) ++{ ++ return set[bit / 8] & (1 << (bit % 8)); ++} ++ ++static void add_entry( ++ int type, unsigned int hash, ++ const char *filename, const unsigned char *digest, ++ int need_symlink, unsigned short old_id) ++{ ++ struct bucket_info *bi; ++ struct entry_info *ei, *found = NULL; ++ unsigned int ndx = (type + hash) % countof(hash_table); ++ ++ for (bi = hash_table[ndx]; bi; bi = bi->next) ++ if (bi->type == type && bi->hash == hash) ++ break; ++ if (!bi) { ++ bi = calloc(1, sizeof(*bi)); ++ if (!bi) return; ++ bi->next = hash_table[ndx]; ++ bi->type = type; ++ bi->hash = hash; ++ hash_table[ndx] = bi; ++ } ++ ++ for (ei = bi->first_entry; ei; ei = ei->next) { ++ if (digest && memcmp(digest, ei->digest, evpmdsize) == 0) { ++ BIO_printf(bio_err, ++ "WARNING: Skipping duplicate certificate in file %s\n", ++ filename); ++ return; ++ } ++ if (!strcmp(filename, ei->filename)) { ++ found = ei; ++ if (!digest) break; ++ } ++ } ++ ei = found; ++ if (!ei) { ++ if (bi->num_needed >= MAX_COLLISIONS) return; ++ ei = calloc(1, sizeof(*ei)); ++ if (!ei) return; ++ ++ ei->old_id = ~0; ++ ei->filename = strdup(filename); ++ if (bi->last_entry) bi->last_entry->next = ei; ++ if (!bi->first_entry) bi->first_entry = ei; ++ bi->last_entry = ei; ++ } ++ ++ if (old_id < ei->old_id) ei->old_id = old_id; ++ if (need_symlink && !ei->need_symlink) { ++ ei->need_symlink = 1; ++ bi->num_needed++; ++ memcpy(ei->digest, digest, evpmdsize); ++ } ++} ++ ++static int handle_symlink(const char *filename, const char *fullpath) ++{ ++ static char xdigit[] = { ++ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, ++ -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, ++ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, ++ -1,10,11,12,13,14,15 ++ }; ++ char linktarget[NAME_MAX], *endptr; ++ unsigned int hash = 0; ++ unsigned char ch; ++ int i, type, id; ++ ssize_t n; ++ ++ for (i = 0; i < 8; i++) { ++ ch = filename[i] - '0'; ++ if (ch >= countof(xdigit) || xdigit[ch] < 0) ++ return -1; ++ hash <<= 4; ++ hash += xdigit[ch]; ++ } ++ if (filename[i++] != '.') return -1; ++ for (type = countof(symlink_extensions) - 1; type > 0; type--) ++ if (strcasecmp(symlink_extensions[type], &filename[i]) == 0) ++ break; ++ i += strlen(symlink_extensions[type]); ++ ++ id = strtoul(&filename[i], &endptr, 10); ++ if (*endptr != 0) return -1; ++ ++ n = readlink(fullpath, linktarget, sizeof(linktarget)); ++ if (n >= sizeof(linktarget) || n < 0) return -1; ++ linktarget[n] = 0; ++ ++ DEBUG("Found existing symlink %s for %08x (%d), certname %s\n", ++ filename, hash, type, linktarget); ++ add_entry(type, hash, linktarget, NULL, 0, id); ++ return 0; ++} ++ ++static int handle_certificate(const char *filename, const char *fullpath) ++{ ++ STACK_OF(X509_INFO) *inf; ++ X509_INFO *x; ++ BIO *b; ++ const char *ext; ++ unsigned char digest[EVP_MAX_MD_SIZE]; ++ X509_NAME *name = NULL; ++ int i, type, ret = -1; ++ ++ ext = strrchr(filename, '.'); ++ if (ext == NULL) return 0; ++ for (i = 0; i < countof(file_extensions); i++) { ++ if (strcasecmp(file_extensions[i], ext+1) == 0) ++ break; ++ } ++ if (i >= countof(file_extensions)) return -1; ++ ++ b = BIO_new_file(fullpath, "r"); ++ if (!b) return -1; ++ inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); ++ BIO_free(b); ++ if (!inf) return -1; ++ ++ if (sk_X509_INFO_num(inf) == 1) { ++ x = sk_X509_INFO_value(inf, 0); ++ if (x->x509) { ++ type = TYPE_CERT; ++ name = X509_get_subject_name(x->x509); ++ X509_digest(x->x509, evpmd, digest, NULL); ++ } else if (x->crl) { ++ type = TYPE_CRL; ++ name = X509_CRL_get_issuer(x->crl); ++ X509_CRL_digest(x->crl, evpmd, digest, NULL); ++ } ++ if (name && do_hash_new) ++ add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0); ++ if (name && do_hash_old) ++ add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0); ++ } else { ++ BIO_printf(bio_err, ++ "WARNING: %s does not contain exactly one certificate or CRL: skipping\n", ++ filename); ++ } ++ ++ sk_X509_INFO_pop_free(inf, X509_INFO_free); ++ ++ return ret; ++} ++ ++static int hash_dir(const char *dirname) ++{ ++ struct bucket_info *bi, *nextbi; ++ struct entry_info *ei, *nextei; ++ struct dirent *de; ++ struct stat st; ++ unsigned char idmask[MAX_COLLISIONS / 8]; ++ int i, n, nextid, buflen, ret = -1; ++ const char *pathsep; ++ char *buf; ++ DIR *d; ++ ++ if (access(dirname, R_OK|W_OK|X_OK) != 0) { ++ BIO_printf(bio_err, ++ "ERROR: Access denied '%s'\n", ++ dirname); ++ return -1; ++ } ++ ++ buflen = strlen(dirname); ++ pathsep = (buflen && dirname[buflen-1] == '/') ? "" : "/"; ++ buflen += NAME_MAX + 2; ++ buf = malloc(buflen); ++ if (buf == NULL) ++ goto err; ++ ++ if (do_verbose) printf("Doing %s\n", dirname); ++ d = opendir(dirname); ++ if (!d) goto err; ++ ++ while ((de = readdir(d)) != NULL) { ++ if (snprintf(buf, buflen, "%s%s%s", dirname, pathsep, de->d_name) >= buflen) ++ continue; ++ if (lstat(buf, &st) < 0) ++ continue; ++ if (S_ISLNK(st.st_mode) && handle_symlink(de->d_name, buf) == 0) ++ continue; ++ handle_certificate(de->d_name, buf); ++ } ++ closedir(d); ++ ++ for (i = 0; i < countof(hash_table); i++) { ++ for (bi = hash_table[i]; bi; bi = nextbi) { ++ nextbi = bi->next; ++ DEBUG("Type %d, hash %08x, num entries %d:\n", bi->type, bi->hash, bi->num_needed); ++ ++ nextid = 0; ++ memset(idmask, 0, (bi->num_needed+7)/8); ++ for (ei = bi->first_entry; ei; ei = ei->next) ++ if (ei->old_id < bi->num_needed) ++ bit_set(idmask, ei->old_id); ++ ++ for (ei = bi->first_entry; ei; ei = nextei) { ++ nextei = ei->next; ++ DEBUG("\t(old_id %d, need_symlink %d) Cert %s\n", ++ ei->old_id, ei->need_symlink, ++ ei->filename); ++ ++ if (ei->old_id < bi->num_needed) { ++ /* Link exists, and is used as-is */ ++ snprintf(buf, buflen, "%08x.%s%d", bi->hash, symlink_extensions[bi->type], ei->old_id); ++ if (do_verbose) printf("link %s -> %s\n", ei->filename, buf); ++ } else if (ei->need_symlink) { ++ /* New link needed (it may replace something) */ ++ while (bit_isset(idmask, nextid)) ++ nextid++; ++ ++ snprintf(buf, buflen, "%s%s%n%08x.%s%d", ++ dirname, pathsep, &n, bi->hash, ++ symlink_extensions[bi->type], ++ nextid); ++ if (do_verbose) printf("link %s -> %s\n", ei->filename, &buf[n]); ++ unlink(buf); ++ symlink(ei->filename, buf); ++ } else if (do_remove_links) { ++ /* Link to be deleted */ ++ snprintf(buf, buflen, "%s%s%n%08x.%s%d", ++ dirname, pathsep, &n, bi->hash, ++ symlink_extensions[bi->type], ++ ei->old_id); ++ if (do_verbose) printf("unlink %s\n", &buf[n]); ++ unlink(buf); ++ } ++ free(ei->filename); ++ free(ei); ++ } ++ free(bi); ++ } ++ hash_table[i] = NULL; ++ } ++ ++ ret = 0; ++err: ++ free(buf); ++ return ret; ++} ++ ++static void c_rehash_usage(void) ++{ ++ printf("\ ++usage: c_rehash <args> <dirs>\n\ ++\n\ ++-compat - create new- and old-style hashed links\n\ ++-old - use old-style hashing for generating links\n\ ++-h - display this help\n\ ++-n - do not remove existing links\n\ ++-v - be more verbose\n\ ++\n"); ++} ++ ++int MAIN(int argc, char **argv) ++{ ++ const char *env, *opt; ++ int i, numargs, r = 0; ++ ++ evpmd = EVP_sha1(); ++ evpmdsize = EVP_MD_size(evpmd); ++ if (bio_err == NULL) ++ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); ++ ++ numargs = argc; ++ for (i = 1; i < argc; i++) { ++ if (argv[i][0] != '-') continue; ++ if (strcmp(argv[i], "--") == 0) { argv[i] = 0; numargs--; break; } ++ opt = &argv[i][1]; ++ if (strcmp(opt, "compat") == 0) { ++ do_hash_new = do_hash_old = 1; ++ } else if (strcmp(opt, "old") == 0) { ++ do_hash_new = 0; ++ do_hash_old = 1; ++ } else if (strcmp(opt, "n") == 0) { ++ do_remove_links = 0; ++ } else if (strcmp(opt, "v") == 0) { ++ do_verbose++; ++ } else { ++ if (strcmp(opt, "h") != 0) ++ BIO_printf(bio_err,"unknown option %s\n", argv[i]); ++ c_rehash_usage(); ++ return 1; ++ } ++ argv[i] = 0; ++ numargs--; ++ } ++ ++ if (numargs > 1) { ++ for (i = 1; i < argc; i++) ++ if (argv[i]) r |= hash_dir(argv[i]); ++ } else if ((env = getenv("SSL_CERT_DIR")) != NULL) { ++ char *e, *m; ++ m = strdup(env); ++ for (e = strtok(m, ":"); e != NULL; e = strtok(NULL, ":")) ++ r |= hash_dir(e); ++ free(m); ++ } else { ++ r |= hash_dir("/etc/ssl/certs"); ++ } ++ ++ return r ? 2 : 0; ++} +diff --git a/tools/Makefile b/tools/Makefile +index bb6fb71..51190fc 100644 +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -13,7 +13,7 @@ CFLAGS= $(INCLUDES) $(CFLAG) + + GENERAL=Makefile + TEST= +-APPS= c_rehash ++APPS= + MISC_APPS= c_hash c_info c_issuer c_name + + all: +@@ -49,7 +49,6 @@ depend: + dclean: + $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new + mv -f Makefile.new $(MAKEFILE) +- rm -f c_rehash + + clean: + rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff +-- +2.2.2 + |