static int unlink_dir(const char *src) { struct stat sb; if (lstat(src, &sb)) { perror(src); return (1); } if (S_ISDIR(sb.st_mode)) { DIR *dirp; struct dirent *dp; /* allow read and write access always */ chmod(src, (sb.st_mode | S_IRUSR | S_IWUSR) & 07777); dirp = opendir(src); if (dirp == NULL) { perror(src); return (1); } while ((dp = readdir(dirp)) != NULL) { char *f; if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0 || dp->d_ino == 0) continue; GFARM_MALLOC_ARRAY(f, strlen(src) + 1 + strlen(dp->d_name) + 1); if (f == NULL) { print_errmsg(dp->d_name, NULL, "not enough memory"); return (1); } strcpy(f, src); strcat(f, "/"); strcat(f, dp->d_name); (void)unlink_dir(f); free(f); } closedir(dirp); if (rmdir(src)) { perror(src); return (1); } } else if (unlink(src)) { /* if 'src' is not a directory, try to unlink. */ perror(src); return (1); } return (0); }
static void delete_invalid_file_or_directory(char *pathname) { if (delete_invalid_file) { if (unlink_dir(pathname) == 0) print_msg(pathname, NULL, "deleted"); else print_errmsg(pathname, NULL, "cannot delete"); } }
static void delete_invalid_file_or_directory(char *pathname) { if (delete_invalid_file) { if (unlink_dir(pathname) == 0) printf("%s on %s: deleted\n", pathname, gfarm_host_get_self_name()); else print_errmsg(pathname, "cannot delete"); } }
static int unlink_dir(const char *src) { struct stat sb; if (lstat(src, &sb)) { perror(src); return (1); } if (S_ISDIR(sb.st_mode)) { DIR *dirp; struct dirent *dp; dirp = opendir(src); if (dirp == NULL) { perror(src); return (1); } while ((dp = readdir(dirp)) != NULL) { char *f; if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0 || dp->d_ino == 0) continue; f = malloc(strlen(src) + 1 + strlen(dp->d_name) + 1); if (f == NULL) { print_errmsg(dp->d_name, "not enough memory"); return (1); } strcpy(f, src); strcat(f, "/"); strcat(f, dp->d_name); (void)unlink_dir(f); free(f); } closedir(dirp); if (rmdir(src)) { perror(src); return (1); } } else if (unlink(src)) { /* if 'src' is not a directory, try to unlink. */ perror(src); return (1); } return (0); }
static void unlink_dir(const char *path) { DIR *dp; char buf[PATH_MAX]; if ((dp = opendir(path)) != NULL) { struct dirent entbuf, *entp; while (readdir_r(dp, &entbuf, &entp) == 0 && entp != NULL) { if (strcmp(entp->d_name, ".") == 0 || strcmp(entp->d_name, "..") == 0) continue; snprintf(buf, sizeof(buf), "%s/%s", path, entp->d_name); unlink_dir(buf); } closedir(dp); } unlink(path); }
__attribute__((noreturn)) static void *daemon_close_notify_thread(void *_close_notify_fd) { int close_notify_fd = (int)((char *)_close_notify_fd - (char *)NULL); char b; ssize_t r; Redo: r = read(close_notify_fd, &b, 1); if (r == -1 && errno == EINTR) goto Redo; if (r > 0) goto Redo; /* close or error */ /* unlink the temporary directory and socket file */ unlink_dir(dirname(daemon_vars.nb->sun_.sun_path)); _exit(0); }
int neverbleed_init(neverbleed_t *nb, char *errbuf) { int pipe_fds[2] = {-1, -1}, listen_fd = -1; char *tempdir = NULL; const RSA_METHOD *default_method = RSA_PKCS1_SSLeay(); rsa_method.rsa_pub_enc = default_method->rsa_pub_enc; rsa_method.rsa_pub_dec = default_method->rsa_pub_dec; rsa_method.rsa_verify = default_method->rsa_verify; /* setup the daemon */ if (pipe(pipe_fds) != 0) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "pipe(2) failed:%s", strerror(errno)); goto Fail; } fcntl(pipe_fds[1], F_SETFD, O_CLOEXEC); if ((tempdir = strdup("/tmp/openssl-privsep.XXXXXX")) == NULL) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "no memory"); goto Fail; } if (mkdtemp(tempdir) == NULL) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to create temporary directory under /tmp:%s", strerror(errno)); goto Fail; } memset(&nb->sun_, 0, sizeof(nb->sun_)); nb->sun_.sun_family = AF_UNIX; snprintf(nb->sun_.sun_path, sizeof(nb->sun_.sun_path), "%s/_", tempdir); RAND_bytes(nb->auth_token, sizeof(nb->auth_token)); if ((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "socket(2) failed:%s", strerror(errno)); goto Fail; } if (bind(listen_fd, (void *)&nb->sun_, sizeof(nb->sun_)) != 0) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to bind to %s:%s", nb->sun_.sun_path, strerror(errno)); goto Fail; } if (listen(listen_fd, SOMAXCONN) != 0) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "listen(2) failed:%s", strerror(errno)); goto Fail; } switch (fork()) { case -1: snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "fork(2) failed:%s", strerror(errno)); goto Fail; case 0: close(pipe_fds[1]); #ifdef __linux__ prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); #endif memcpy(daemon_auth_token, nb->auth_token, NEVERBLEED_AUTH_TOKEN_SIZE); daemon_main(listen_fd, pipe_fds[0], tempdir); break; default: break; } close(listen_fd); listen_fd = -1; close(pipe_fds[0]); pipe_fds[0] = -1; /* setup engine */ if ((nb->engine = ENGINE_new()) == NULL || !ENGINE_set_id(nb->engine, "neverbleed") || !ENGINE_set_name(nb->engine, "privilege separation software engine") || !ENGINE_set_RSA(nb->engine, &rsa_method)) { snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to initialize the OpenSSL engine"); goto Fail; } ENGINE_add(nb->engine); /* setup thread key */ pthread_key_create(&nb->thread_key, dispose_thread_data); free(tempdir); return 0; Fail: if (pipe_fds[0] != -1) close(pipe_fds[0]); if (pipe_fds[1] != -1) close(pipe_fds[1]); if (tempdir != NULL) { unlink_dir(tempdir); free(tempdir); } if (listen_fd != -1) close(listen_fd); if (nb->engine != NULL) { ENGINE_free(nb->engine); nb->engine = NULL; } return -1; }