-static bool refresh_invitation_key(meshlink_handle_t *mesh) {
- char filename[PATH_MAX];
-
- pthread_mutex_lock(&(mesh->mesh_mutex));
-
- snprintf(filename, sizeof(filename), "%s" SLASH "invitations", mesh->confbase);
-
- if(mkdir(filename, 0700) && errno != EEXIST) {
- logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
- meshlink_errno = MESHLINK_ESTORAGE;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
-
- // Count the number of valid invitations, clean up old ones
- DIR *dir = opendir(filename);
-
- if(!dir) {
- logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", filename, strerror(errno));
- meshlink_errno = MESHLINK_ESTORAGE;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
-
- errno = 0;
- int count = 0;
- struct dirent *ent;
- time_t deadline = time(NULL) - 604800; // 1 week in the past
-
- while((ent = readdir(dir))) {
- if(strlen(ent->d_name) != 24) {
- continue;
- }
-
- char invname[PATH_MAX];
- struct stat st;
-
- if(snprintf(invname, sizeof(invname), "%s" SLASH "%s", filename, ent->d_name) >= PATH_MAX) {
- logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "%s", filename, ent->d_name);
- continue;
- }
-
- if(!stat(invname, &st)) {
- if(mesh->invitation_key && deadline < st.st_mtime) {
- count++;
- } else {
- unlink(invname);
- }
- } else {
- logger(mesh, MESHLINK_DEBUG, "Could not stat %s: %s\n", invname, strerror(errno));
- errno = 0;
- }
- }
-
- if(errno) {
- logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", filename, strerror(errno));
- closedir(dir);
- meshlink_errno = MESHLINK_ESTORAGE;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
-
- closedir(dir);
-
- snprintf(filename, sizeof(filename), "%s" SLASH "invitations" SLASH "ecdsa_key.priv", mesh->confbase);
-
- // Remove the key if there are no outstanding invitations.
- if(!count) {
- unlink(filename);
-
- if(mesh->invitation_key) {
- ecdsa_free(mesh->invitation_key);
- mesh->invitation_key = NULL;
- }
- }
-
- if(mesh->invitation_key) {
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return true;
- }
-
- // Create a new key if necessary.
- FILE *f = fopen(filename, "rb");
-
- if(!f) {
- if(errno != ENOENT) {
- logger(mesh, MESHLINK_DEBUG, "Could not read %s: %s\n", filename, strerror(errno));
- meshlink_errno = MESHLINK_ESTORAGE;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
-
- mesh->invitation_key = ecdsa_generate();
-
- if(!mesh->invitation_key) {
- logger(mesh, MESHLINK_DEBUG, "Could not generate a new key!\n");
- meshlink_errno = MESHLINK_EINTERNAL;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
-
- f = fopen(filename, "wb");
-
- if(!f) {
- logger(mesh, MESHLINK_DEBUG, "Could not write %s: %s\n", filename, strerror(errno));
- meshlink_errno = MESHLINK_ESTORAGE;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }