comparison libpurple/certificate.c @ 21647:a57adf1de9cb

Patch from Florian Quze (the InstantBird dude) to add a search path for certificates. Closes #3634. The original patch was to set the path purple searches for certificats. I changed it to allow for multiple search paths. This is similar to how purple searches for plugins in multiple paths.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Mon, 26 Nov 2007 09:28:15 +0000
parents 7109257d4612
children b05a8f1db1c3
comparison
equal deleted inserted replaced
21646:2a2496044eef 21647:a57adf1de9cb
625 g_free(el); 625 g_free(el);
626 } 626 }
627 627
628 /** System directory to probe for CA certificates */ 628 /** System directory to probe for CA certificates */
629 /* This is set in the lazy_init function */ 629 /* This is set in the lazy_init function */
630 static const gchar *x509_ca_syspath = NULL; 630 static GList *x509_ca_paths = NULL;
631 631
632 /** A list of loaded CAs, populated from the above path whenever the lazy_init 632 /** A list of loaded CAs, populated from the above path whenever the lazy_init
633 happens. Contains pointers to x509_ca_elements */ 633 happens. Contains pointers to x509_ca_elements */
634 static GList *x509_ca_certs = NULL; 634 static GList *x509_ca_certs = NULL;
635 635
672 { 672 {
673 PurpleCertificateScheme *x509; 673 PurpleCertificateScheme *x509;
674 GDir *certdir; 674 GDir *certdir;
675 const gchar *entry; 675 const gchar *entry;
676 GPatternSpec *pempat; 676 GPatternSpec *pempat;
677 GList *iter = NULL;
677 678
678 if (x509_ca_initialized) return TRUE; 679 if (x509_ca_initialized) return TRUE;
679 680
680 /* Check that X.509 is registered */ 681 /* Check that X.509 is registered */
681 x509 = purple_certificate_find_scheme(x509_ca.scheme_name); 682 x509 = purple_certificate_find_scheme(x509_ca.scheme_name);
685 "is not yet registered. Maybe it will be " 686 "is not yet registered. Maybe it will be "
686 "better later.\n"); 687 "better later.\n");
687 return FALSE; 688 return FALSE;
688 } 689 }
689 690
690 /* Attempt to point at the appropriate system path */
691 if (NULL == x509_ca_syspath) {
692 #ifdef _WIN32
693 x509_ca_syspath = g_build_filename(DATADIR,
694 "ca-certs", NULL);
695 #else
696 x509_ca_syspath = g_build_filename(DATADIR,
697 "purple", "ca-certs", NULL);
698 #endif
699 }
700
701 /* Populate the certificates pool from the system path */
702 certdir = g_dir_open(x509_ca_syspath, 0, NULL);
703 g_return_val_if_fail(certdir, FALSE);
704
705 /* Use a glob to only read .pem files */ 691 /* Use a glob to only read .pem files */
706 pempat = g_pattern_spec_new("*.pem"); 692 pempat = g_pattern_spec_new("*.pem");
707 693
708 while ( (entry = g_dir_read_name(certdir)) ) { 694 /* Populate the certificates pool from the search path(s) */
709 gchar *fullpath; 695 for (iter = x509_ca_paths; iter; iter = iter->next) {
710 PurpleCertificate *crt; 696 certdir = g_dir_open(iter->data, 0, NULL);
711 697 if (!certdir) {
712 if ( !g_pattern_match_string(pempat, entry) ) { 698 purple_debug_error("certificate/x509/ca", "Couldn't open location '%s'\n", iter->data);
713 continue; 699 continue;
714 } 700 }
715 701
716 fullpath = g_build_filename(x509_ca_syspath, entry, NULL); 702 while ( (entry = g_dir_read_name(certdir)) ) {
717 703 gchar *fullpath;
718 /* TODO: Respond to a failure in the following? */ 704 PurpleCertificate *crt;
719 crt = purple_certificate_import(x509, fullpath); 705
720 706 if ( !g_pattern_match_string(pempat, entry) ) {
721 if (x509_ca_quiet_put_cert(crt)) { 707 continue;
722 purple_debug_info("certificate/x509/ca", 708 }
723 "Loaded %s\n", 709
724 fullpath); 710 fullpath = g_build_filename(iter->data, entry, NULL);
725 } else { 711
726 purple_debug_error("certificate/x509/ca", 712 /* TODO: Respond to a failure in the following? */
727 "Failed to load %s\n", 713 crt = purple_certificate_import(x509, fullpath);
728 fullpath); 714
715 if (x509_ca_quiet_put_cert(crt)) {
716 purple_debug_info("certificate/x509/ca",
717 "Loaded %s\n",
718 fullpath);
719 } else {
720 purple_debug_error("certificate/x509/ca",
721 "Failed to load %s\n",
722 fullpath);
723 }
724
725 purple_certificate_destroy(crt);
726 g_free(fullpath);
729 } 727 }
730 728 g_dir_close(certdir);
731 purple_certificate_destroy(crt);
732 g_free(fullpath);
733 } 729 }
734 730
735 g_pattern_spec_free(pempat); 731 g_pattern_spec_free(pempat);
736 g_dir_close(certdir); 732
737
738 purple_debug_info("certificate/x509/ca", 733 purple_debug_info("certificate/x509/ca",
739 "Lazy init completed.\n"); 734 "Lazy init completed.\n");
740 x509_ca_initialized = TRUE; 735 x509_ca_initialized = TRUE;
741 return TRUE; 736 return TRUE;
742 } 737 }
743 738
744 static gboolean 739 static gboolean
745 x509_ca_init(void) 740 x509_ca_init(void)
746 { 741 {
742 /* Attempt to point at the appropriate system path */
743 if (NULL == x509_ca_paths) {
744 #ifdef _WIN32
745 x509_ca_paths = g_list_append(NULL, g_build_filename(DATADIR,
746 "ca-certs", NULL));
747 #else
748 x509_ca_paths = g_list_append(NULL, g_build_filename(DATADIR,
749 "purple", "ca-certs", NULL));
750 #endif
751 }
752
747 /* Attempt to initialize now, but if it doesn't work, that's OK; 753 /* Attempt to initialize now, but if it doesn't work, that's OK;
748 it will get done later */ 754 it will get done later */
749 if ( ! x509_ca_lazy_init()) { 755 if ( ! x509_ca_lazy_init()) {
750 purple_debug_info("certificate/x509/ca", 756 purple_debug_info("certificate/x509/ca",
751 "Init failed, probably because a " 757 "Init failed, probably because a "
752 "dependency is not yet registered. " 758 "dependency is not yet registered. "
753 "It has been deferred to later.\n"); 759 "It has been deferred to later.\n");
754 } 760 }
755 761
756 return TRUE; 762 return TRUE;
757 } 763 }
758 764
759 static void 765 static void
760 x509_ca_uninit(void) 766 x509_ca_uninit(void)
766 x509_ca_element_free(el); 772 x509_ca_element_free(el);
767 } 773 }
768 g_list_free(x509_ca_certs); 774 g_list_free(x509_ca_certs);
769 x509_ca_certs = NULL; 775 x509_ca_certs = NULL;
770 x509_ca_initialized = FALSE; 776 x509_ca_initialized = FALSE;
777 g_list_foreach(x509_ca_paths, (GFunc)g_free, NULL);
778 g_list_free(x509_ca_paths);
779 x509_ca_paths = NULL;
771 } 780 }
772 781
773 /** Look up a ca_element by dn */ 782 /** Look up a ca_element by dn */
774 static x509_ca_element * 783 static x509_ca_element *
775 x509_ca_locate_cert(GList *lst, const gchar *dn) 784 x509_ca_locate_cert(GList *lst, const gchar *dn)
1904 g_free(activ_str); 1913 g_free(activ_str);
1905 g_free(expir_str); 1914 g_free(expir_str);
1906 g_byte_array_free(sha_bin, TRUE); 1915 g_byte_array_free(sha_bin, TRUE);
1907 } 1916 }
1908 1917
1918 void purple_certificate_add_ca_search_path(const char *path)
1919 {
1920 if (g_list_find_custom(x509_ca_paths, path, (GCompareFunc)strcmp))
1921 return;
1922 x509_ca_paths = g_list_append(x509_ca_paths, g_strdup(path));
1923 }
1924