Tekn.dr. Göran Pulkkis Överlärare i Datateknik Avancerad SSL-programmering II 1 Innehåll Makron för generisk stackhantering Hantering av konfigureringsfiler Certifikathantering 2 1
Makron för generisk stackhantering STACK_OF(TYPE) *sk_type_net_null(void); Skapar en ny tom stack för element med datatypen TYPE void sk_type_free(stack_of(type) *st); Minnesutrymmet för en stack friges void sk_type_pop_free(stack_of(type) *st, void(*free_func(type *)); Minnesutrymmet alla element i en stack och för själva stacken friges. Funktionen free_func friger minnesutrymmet för ett element med datatypen TYPE 3 Makron för generisk stackhantering void sk_type_zero(stack_of(type) *st); Tömmer en stack STACK_OF(TYPE) *sk_type_dup(stack_of(type) *st); Skapar en kopia av en stack int sk_type_push(stack_of(type) *st, TYPE *val); Placerar ett element på stacken TYPE *sk_type_pop(stack_of(type) *st); Tar bort ett element från stacken 4 2
Makron för generisk stackhantering int sk_type_unshift(stack_of(type) *st, TYPE *val); Placerar ett element underst i stacken TYPE *sk_type_shift(stack_of(type) *st); Tar bort stackens understa element int sk_type_num(stack_of(type) *st); Returnerar antalet element i stacken TYPE *sk_type_value(stack_of(type) *st, int i); Utpekar stackelementet med index i (stackens understa element har index 0) 5 Makron för generisk stackhantering TYPE *sk_type_set(stack_of(type) *st, int i, TYPE *val); *val ersätter stackelementet med index i TYPE *sk_type_delete(stack_of(type) *st, int i); Stackelementet med index i raderas TYPE *sk_type_delete_ptr(stack_of(type) *st, TYPE *ptr); Stackelementet med adressen ptr raderas int sk_type_insert(stack_of(type) *st, TYPE *val, int i); *val införs som stackelement med index i 6 3
Hantering av konfigureringsfiler # The sample config file testconf.cnf GlobalVar = foo GlobalNum = 12 [Params] SectionName = mysection [mysection] myvar = bar mynum = 7 7 Posttypen CONF_VALUE anger ett värde i en.cnf-fil typedef struct { char *section; char *name; char *value; CONF_VALUE; 8 4
Program för hantering av testconf.cnf #include <stdio.h> #include <stdlib.h> #include <openssl/conf.h> void handle_error (const char *file, int lineno, const char *msg) { fprintf (stderr, "** %s:%i %s\n", file, lineno, msg); ERR_print_errors_fp (stderr); exit (-1); #define int_error(msg) handle_error( FILE, LINE, msg) #define GLOB_VAR "GlobalVar" #define GLOB_NUM "GlobalNum" #define PARAMS "Params" #define SEC_NAME "SectionName" #define CONFFILE "testconf.cnf" 9 Program för hantering av testconf.cnf int main (int argc, char *argv[]) { int i; long i_val, err = 0; char *key, *s_val; STACK_OF (CONF_VALUE) *sec; CONF_VALUE *item; CONF *conf; conf = NCONF_new (NCONF_default ()); if (!NCONF_load (conf, CONFFILE, &err)) { if (err == 0) int_error ("Error opening configuration file"); else { fprintf (stderr, "Error in %s on line %li\n", CONFFILE, err); int_error ("Errors parsing configuration file"); 10 5
Program för hantering av testconf.cnf if (!(s_val = NCONF_get_string (conf, NULL, GLOB_VAR))) { fprintf (stderr, "Error finding \"%s\" in [%s]\n", GLOB_VAR, NULL); int_error ("Error finding string"); printf ("Sec: %s, Key: %s, Val: %s\n", NULL, GLOB_VAR, s_val); #if (OPENSSL_VERSION_NUMBER > 0x00907000L) if (!(err = NCONF_get_number_e (conf, NULL, GLOB_NUM, &i_val))) { fprintf (stderr, "Error finding \"%s\" in [%s]\n", GLOB_NUM, NULL); int_error ("Error finding number"); #else if (!(s_val = NCONF_get_string (conf, NULL, GLOB_NUM))) { fprintf (stderr, "Error finding \"%s\" in [%s]\n", GLOB_VAR, NULL); int_error ("Error finding number"); i_val = atoi (s_val); #endif printf ("Sec: %s, Key: %s, Val: %i\n", NULL, GLOB_VAR, i_val); 11 Program för hantering av testconf.cnf if (!(key = NCONF_get_string (conf, PARAMS, SEC_NAME))) { fprintf (stderr, "Error finding \"%s\" in [%s]\n", SEC_NAME, PARAMS); int_error ("Error finding string"); fprintf (stdout, "Sec: %s, Key: %s, Val: %s\n", PARAMS, SEC_NAME, key); /* the values of mysection are pushed on a stack */ if (!(sec = NCONF_get_section (conf, key))) { fprintf (stderr, "Error finding [%s]\n", key); int_error ("Error finding string"); for (i = 0; i < sk_conf_value_num (sec); i++) { item = sk_conf_value_value (sec, i); printf ("Sec: %s, Key: %s, Val: %s\n", item->section, item->name, item->value); NCONF_free (conf); return 0; 12 6
Exekvering av program för hantering av testconf.cnf goran@xena:~/conf$ gcc -o confprog confprog.c -lssl goran@xena:~/conf$ confprog Sec: (null), Key: GlobalVar, Val: foo Sec: (null), Key: GlobalVar, Val: 12 Sec: Params, Key: SectionName, Val: mysection Sec: mysection, Key: myvar, Val: bar Sec: mysection, Key: mynum, Val: 7 goran@xena:~/conf$ cat testconf.cnf # The sample config file testconf.cnf GlobalVar = foo GlobalNum = 12 [Params] SectionName = mysection [mysection] myvar = bar mynum = 7 13 Certifikathantering Skapa certifikatbegäran ( Certificate Request ) Skapa certifikat från certifikatbegäran Verifiera certifikat 14 7
Skapa certifikatbegäran (Example 10-5) ( Certificate Request ) Begäran av ett X.509-certifikat representeras av en X509_REQ-post Namnet på ett certifikat representeras av en X509_NAME-post En X509_NAME-post är en samling X509_NAME_ENTRYposter En X509_NAME_ENTRY-post består av komponentnamn och värde och identifieras med ett s.k. NID-heltalsvärde En tilläggskomponent ( extension ) representeras av en X509_EXTENSION-post Tilläggskomponenter samlas i en STACK_OF(X509_EXTENSION)-post Privata och publika nycklar hanteras med EVP_PKEY-poster Hash-algoritmer hanteras med EVP_MD-poster 15 Skapa certifikatbegäran (Example 10-5) ( Certificate Request ) Publika nyckeln införs med funktionen X509_REQ_set_pubkey() Införsel av komponent med funktionerna OBJ_txt2nid() returnerar NID-värde X509_NAME_ENTRY_create_by_NID() returnerar pekare på X509_NAME_ENTRY-post X509_NAME_add_entry() Införsel av alla tilläggskomponenter ( extensions ) med funktionen X509_REQ_add_extensions() För signering (RSA eller DSA) funktionerna EVP_PKEY_type() och X509_REQ_sign(). 16 8
Skapa certifikat (Example 10.6) från certifikatbegäran 1. Verifiera och innehållsgranska certifikatbegäran 2. Skapa ett nytt certifikat med komponenterna i certifikatbegäran 3. Inför tilläggskomponenterna från certifikatbegäran 4. Signera certifikatet med den privata CA-nyckeln 17 Skapa certifikat (Example 10.6) från certifikatbegäran En X509v3_CTX-post behövs vid införsel av tilläggskomponenter ( extensions ) Med funktionsanropet X509V3_set_ctx(&ctx,CAcert,cert,NULL,NULL,0) görs införda certifikatkomponenter åtkomliga via en X509v3_CTX-post Funktionen X509V3_EXT_conf() kan därefter skapa och returnera pekare på även en sådan tilläggskomponent, som uträknas ur redan införda certifikatkomponenter. T.ex. subjectkeyindentifier uträknas som ett extrakt ( hash ) av en del av redan införda certifikatkomponenter 18 9
Verifiera certifikat (Example 10.7) Certifikathanteringen behöver en X509-post Hantering av CA-certifikathierarki och av eventuella verifieringsfel behöver en X509_STORE-post Hantering av spärrlistan behöver en X509_LOOKUP-post och genomsökningsfunktionen X509_LOOKUP_file() Verifieringen behöver en X509_STORE_CTX-post samt funktionerna X509_STORE_CTX_init() och X509_verify_cert() 19 10