diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 64042068d..6400cfff6 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -157,6 +157,11 @@ struct private_local_credential_store_t { */ linked_list_t *private_keys; + /** + * mutex controls access to the linked lists of secret keys + */ + pthread_mutex_t keys_mutex; + /** * list of X.509 certificates with public keys */ @@ -201,8 +206,9 @@ static status_t get_key(linked_list_t *keys, prio_t best_prio = PRIO_UNDEFINED; chunk_t found = chunk_empty; shared_key_t *shared_key; + iterator_t *iterator; - iterator_t *iterator = keys->create_iterator(keys, TRUE); + iterator = keys->create_iterator(keys, TRUE); while (iterator->iterate(iterator, (void**)&shared_key)) { @@ -260,7 +266,12 @@ static status_t get_shared_key(private_local_credential_store_t *this, identification_t *my_id, identification_t *other_id, chunk_t *secret) { - return get_key(this->shared_keys, my_id, other_id, secret); + status_t status; + + pthread_mutex_lock(&(this->keys_mutex)); + status = get_key(this->shared_keys, my_id, other_id, secret); + pthread_mutex_unlock(&(this->keys_mutex)); + return status; } /** @@ -270,7 +281,12 @@ static status_t get_eap_key(private_local_credential_store_t *this, identification_t *my_id, identification_t *other_id, chunk_t *secret) { - return get_key(this->eap_keys, my_id, other_id, secret); + status_t status; + + pthread_mutex_lock(&(this->keys_mutex)); + status = get_key(this->eap_keys, my_id, other_id, secret); + pthread_mutex_unlock(&(this->keys_mutex)); + return status; } /** @@ -341,8 +357,10 @@ static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t * rsa_public_key_t *pubkey) { rsa_private_key_t *found = NULL, *current; + iterator_t *iterator; - iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE); + pthread_mutex_lock(&(this->keys_mutex)); + iterator = this->private_keys->create_iterator(this->private_keys, TRUE); while (iterator->iterate(iterator, (void**)¤t)) { @@ -353,6 +371,7 @@ static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t * } } iterator->destroy(iterator); + pthread_mutex_unlock(&(this->keys_mutex)); return found; } @@ -1274,7 +1293,7 @@ static err_t extract_secret(chunk_t *secret, chunk_t *line) /** * Implements local_credential_store_t.load_secrets */ -static void load_secrets(private_local_credential_store_t *this) +static void load_secrets(private_local_credential_store_t *this, bool reload) { FILE *fd = fopen(SECRETS_FILE, "r"); @@ -1284,7 +1303,8 @@ static void load_secrets(private_local_credential_store_t *this) int line_nr = 0; chunk_t chunk, src, line; - DBG1(DBG_CFG, "loading secrets from \"%s\"", SECRETS_FILE); + DBG1(DBG_CFG, "%sloading secrets from \"%s\"", + reload? "re":"", SECRETS_FILE); fseek(fd, 0, SEEK_END); chunk.len = ftell(fd); @@ -1292,9 +1312,25 @@ static void load_secrets(private_local_credential_store_t *this) chunk.ptr = malloc(chunk.len); bytes = fread(chunk.ptr, 1, chunk.len, fd); fclose(fd); - src = chunk; + pthread_mutex_lock(&(this->keys_mutex)); + if (reload) + { + DBG1(DBG_CFG, " forgetting old secrets"); + this->private_keys->destroy_offset(this->private_keys, + offsetof(rsa_private_key_t, destroy)); + this->private_keys = linked_list_create(); + + this->shared_keys->destroy_function(this->shared_keys, + (void*)shared_key_destroy); + this->shared_keys = linked_list_create(); + + this->eap_keys->destroy_function(this->eap_keys, + (void*)shared_key_destroy); + this->eap_keys = linked_list_create(); + } + while (fetchline(&src, &line)) { chunk_t ids, token; @@ -1452,6 +1488,7 @@ static void load_secrets(private_local_credential_store_t *this) } error: free(chunk.ptr); + pthread_mutex_unlock(&(this->keys_mutex)); } else { @@ -1468,10 +1505,17 @@ static void destroy(private_local_credential_store_t *this) this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy)); this->auth_certs->destroy_offset(this->auth_certs, offsetof(x509_t, destroy)); this->ca_infos->destroy_offset(this->ca_infos, offsetof(ca_info_t, destroy)); + + pthread_mutex_lock(&(this->acerts_mutex)); this->acerts->destroy_offset(this->acerts, offsetof(x509ac_t, destroy)); + pthread_mutex_unlock(&(this->acerts_mutex)); + + pthread_mutex_lock(&(this->keys_mutex)); this->private_keys->destroy_offset(this->private_keys, offsetof(rsa_private_key_t, destroy)); this->shared_keys->destroy_function(this->shared_keys, (void*)shared_key_destroy); this->eap_keys->destroy_function(this->eap_keys, (void*)shared_key_destroy); + pthread_mutex_unlock(&(this->keys_mutex)); + free(this); } @@ -1508,10 +1552,11 @@ local_credential_store_t * local_credential_store_create(void) this->public.credential_store.load_attr_certificates = (void (*) (credential_store_t*))load_attr_certificates; this->public.credential_store.load_ocsp_certificates = (void (*) (credential_store_t*))load_ocsp_certificates; this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls; - this->public.credential_store.load_secrets = (void (*) (credential_store_t*))load_secrets; + this->public.credential_store.load_secrets = (void (*) (credential_store_t*,bool))load_secrets; this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy; - /* initialize the mutex */ + /* initialize the mutexes */ + pthread_mutex_init(&(this->keys_mutex), NULL); pthread_mutex_init(&(this->acerts_mutex), NULL); /* private variables */ diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index 720038238..aa2909977 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -1471,6 +1471,10 @@ static void stroke_list(stroke_msg_t *msg, FILE *out) */ static void stroke_reread(stroke_msg_t *msg, FILE *out) { + if (msg->reread.flags & REREAD_SECRETS) + { + charon->credentials->load_secrets(charon->credentials, TRUE); + } if (msg->reread.flags & REREAD_CACERTS) { charon->credentials->load_ca_certificates(charon->credentials); diff --git a/src/charon/daemon.c b/src/charon/daemon.c index 37699f83f..a860c7b41 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -300,7 +300,7 @@ static void initialize(private_daemon_t *this, bool syslog, level_t levels[]) this->public.credentials->load_attr_certificates(this->public.credentials); this->public.credentials->load_ocsp_certificates(this->public.credentials); this->public.credentials->load_crls(this->public.credentials); - this->public.credentials->load_secrets(this->public.credentials); + this->public.credentials->load_secrets(this->public.credentials, FALSE); this->public.interfaces = interface_manager_create(); this->public.backends = backend_manager_create(); diff --git a/src/ipsec/ipsec.in b/src/ipsec/ipsec.in index 34b1eae58..f9e8bfabf 100755 --- a/src/ipsec/ipsec.in +++ b/src/ipsec/ipsec.in @@ -110,8 +110,7 @@ down) fi exit 0 ;; -listalgs|listpubkeys|\listcards|\ -rereadsecrets|rereadgroups) +listalgs|listpubkeys|\listcards|\rereadgroups) op="$1" shift if test -e $IPSEC_PLUTO_PID @@ -123,8 +122,8 @@ rereadsecrets|rereadgroups) listcerts|listcacerts|listaacerts|\ listacerts|listgroups|listocspcerts|\ listcainfos|listcrls|listocsp|listall|\ -rereadcacerts|rereadaacerts|rereadacerts|\ -rereadocspcerts|rereadcrls|\ +rereadsecrets|rereadcacerts|rereadaacerts|\ +rereadacerts|rereadocspcerts|rereadcrls|\ rereadall|purgeocsp) op="$1" shift diff --git a/src/libstrongswan/credential_store.h b/src/libstrongswan/credential_store.h index 29381cd47..43c0d2ae8 100755 --- a/src/libstrongswan/credential_store.h +++ b/src/libstrongswan/credential_store.h @@ -296,12 +296,13 @@ struct credential_store_t { /** * @brief Loads secrets in ipsec.secrets * - * Currently, all RSA private key files must be in unencrypted form - * either in DER or PEM format. + * RSA private key files can be either in DER or PEM format + * Optional encryption with a passphrase supported * * @param this calling object + * @param reload are the secrets to be reloaded */ - void (*load_secrets) (credential_store_t *this); + void (*load_secrets) (credential_store_t *this, bool reload); /** * @brief Destroys a credential_store_t object. diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h index 94e07d465..b610678fa 100644 --- a/src/stroke/stroke.h +++ b/src/stroke/stroke.h @@ -72,18 +72,20 @@ typedef enum reread_flag_t reread_flag_t; enum reread_flag_t { /** don't reread anything */ REREAD_NONE = 0x0000, + /** reread all secret keys */ + REREAD_SECRETS = 0x0001, /** reread all ca certs */ - REREAD_CACERTS = 0x0001, + REREAD_CACERTS = 0x0002, /** reread all ocsp signer certs */ - REREAD_OCSPCERTS = 0x0002, + REREAD_OCSPCERTS = 0x0004, /** reread all aa certs */ - REREAD_AACERTS = 0x0004, + REREAD_AACERTS = 0x0008, /** reread all attribute certs */ - REREAD_ACERTS = 0x0008, + REREAD_ACERTS = 0x0010, /** reread all crls */ - REREAD_CRLS = 0x0010, + REREAD_CRLS = 0x0020, /** all reread options */ - REREAD_ALL = 0x001F, + REREAD_ALL = 0x003F, }; typedef enum purge_flag_t purge_flag_t;