=== modified file 'debian/mandos-client.postinst' --- debian/mandos-client.postinst 2008-09-19 17:30:43 +0000 +++ debian/mandos-client.postinst 2008-09-26 04:54:35 +0000 @@ -29,7 +29,7 @@ add_mandos_user(){ if ! getent passwd mandos >/dev/null; then adduser --disabled-password --quiet --system \ - --home /var/run/mandos --no-create-home \ + --home /nonexistent --no-create-home \ --gecos "Mandos password system" --group mandos fi } === modified file 'debian/mandos.postinst' --- debian/mandos.postinst 2008-09-19 17:30:43 +0000 +++ debian/mandos.postinst 2008-09-26 04:54:35 +0000 @@ -21,7 +21,7 @@ configure) if ! getent passwd mandos >/dev/null; then adduser --disabled-password --quiet --system \ - --home /var/run/mandos --no-create-home \ + --home /nonexistent --no-create-home \ --gecos "Mandos password system" --group mandos fi ;; === modified file 'plugin-runner.c' --- plugin-runner.c 2008-09-23 18:46:17 +0000 +++ plugin-runner.c 2008-09-26 04:54:35 +0000 @@ -846,12 +846,12 @@ perror("sigaction"); _exit(EXIT_FAILURE); } - ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); + ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); if(ret < 0){ perror("sigprocmask"); _exit(EXIT_FAILURE); } - + ret = dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */ if(ret == -1){ perror("dup2"); @@ -907,12 +907,11 @@ if (maxfd < new_plugin->fd){ maxfd = new_plugin->fd; } - } closedir(dir); dir = NULL; - + for(plugin *p = plugin_list; p != NULL; p = p->next){ if(p->pid != 0){ break; @@ -923,7 +922,7 @@ free_plugin_list(); } } - + /* Main loop while running plugins exist */ while(plugin_list){ fd_set rfds = rfds_all; @@ -969,6 +968,10 @@ goto fallback; } + plugin *next_plugin = proc->next; + free_plugin(proc); + proc = next_plugin; + /* We are done modifying process list, so unblock signal */ ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); @@ -982,14 +985,11 @@ break; } - plugin *next_plugin = proc->next; - free_plugin(proc); - proc = next_plugin; continue; } /* This process exited nicely, so print its buffer */ - + bool bret = print_out_password(proc->buffer, proc->buffer_length); if(not bret){ @@ -1061,7 +1061,7 @@ perror("sigaction"); exitstatus = EXIT_FAILURE; } - + if(custom_argv != NULL){ for(char **arg = custom_argv+1; *arg != NULL; arg++){ free(*arg); @@ -1073,7 +1073,7 @@ closedir(dir); } - /* Free the process list and kill the processes */ + /* Kill the processes */ for(plugin *p = plugin_list; p != NULL; p = p->next){ if(p->pid != 0){ close(p->fd); @@ -1092,7 +1092,7 @@ if(errno != ECHILD){ perror("wait"); } - + free_plugin_list(); free(plugindir); === modified file 'plugins.d/usplash.c' --- plugins.d/usplash.c 2008-09-24 23:03:31 +0000 +++ plugins.d/usplash.c 2008-09-26 04:54:35 +0000 @@ -27,6 +27,71 @@ interrupted_by_signal = 1; } +static bool usplash_write(const char *cmd, const char *arg){ + /* + * usplash_write("TIMEOUT", "15"); -> "TIMEOUT 15\0" + * usplash_write("PULSATE", NULL); -> "PULSATE\0" + * SEE ALSO + * usplash_write(8) + */ + int ret; + int fifo_fd; + do{ + fifo_fd = open("/dev/.initramfs/usplash_fifo", O_WRONLY); + if(fifo_fd == -1 and (errno != EINTR or interrupted_by_signal)){ + return false; + } + }while(fifo_fd == -1); + + const char *cmd_line; + char *cmd_line_alloc = NULL; + if(arg == NULL){ + cmd_line = cmd; + ret = (int)strlen(cmd); + }else{ + do{ + ret = asprintf(&cmd_line_alloc, "%s %s", cmd, arg); + if(ret == -1 and (errno != EINTR or interrupted_by_signal)){ + int e = errno; + close(fifo_fd); + errno = e; + return false; + } + }while(ret == -1); + cmd_line = cmd_line_alloc; + } + + size_t cmd_line_len = (size_t)ret + 1; + size_t written = 0; + while(not interrupted_by_signal and written < cmd_line_len){ + ret = write(fifo_fd, cmd_line + written, + cmd_line_len - written); + if(ret == -1){ + if(errno != EINTR or interrupted_by_signal){ + int e = errno; + close(fifo_fd); + free(cmd_line_alloc); + errno = e; + return false; + } else { + continue; + } + } + written += (size_t)ret; + } + free(cmd_line_alloc); + do{ + ret = close(fifo_fd); + if(ret == -1 and (errno != EINTR or interrupted_by_signal)){ + return false; + } + }while(ret == -1); + if(interrupted_by_signal){ + return false; + } + return true; +} + int main(__attribute__((unused))int argc, __attribute__((unused))char **argv){ int ret = 0; @@ -64,8 +129,8 @@ pid_t usplash_pid = 0; char *cmdline = NULL; size_t cmdline_len = 0; + const char usplash_name[] = "/sbin/usplash"; { - const char usplash_name[] = "/sbin/usplash"; DIR *proc_dir = opendir("/proc"); if(proc_dir == NULL){ free(prompt); @@ -217,109 +282,129 @@ /* Write command to FIFO */ if(not interrupted_by_signal){ - int fifo_fd = open("/dev/.initramfs/usplash_fifo", O_WRONLY); - if(fifo_fd == -1){ - perror("open"); - free(prompt); - return EXIT_FAILURE; - } - char *command; - ret = asprintf(&command, "INPUTQUIET %s", prompt); - if(ret == -1){ - perror("asprintf"); - free(prompt); - return EXIT_FAILURE; - } - free(prompt); - - size_t command_len = (size_t)ret + 1; - size_t written = 0; - while(not interrupted_by_signal and written < command_len){ - ret = write(fifo_fd, command + written, command_len - written); - if(ret == -1){ - if(interrupted_by_signal){ - break; - } - perror("write"); - if(written == 0){ - free(command); - return EXIT_FAILURE; - } - an_error_occured = true; - break; - } - written += (size_t)ret; - } - ret = close(fifo_fd); - if(ret == -1 and not interrupted_by_signal){ - an_error_occured = true; - } - free(command); - }else{ - free(prompt); - } + if(not usplash_write("TIMEOUT", "0") + and (errno != EINTR)){ + perror("usplash_write"); + an_error_occured = true; + } + } + if(not interrupted_by_signal and not an_error_occured){ + if(not usplash_write("INPUTQUIET", prompt) + and (errno != EINTR)){ + perror("usplash_write"); + an_error_occured = true; + } + } + free(prompt); - { + /* This is not really a loop; while() is used to be able to "break" + out of it; those breaks are marked "Big" */ + while(not interrupted_by_signal and not an_error_occured){ char *buf = NULL; size_t buf_len = 0; + /* Open FIFO */ + int fifo_fd; + do{ + fifo_fd = open("/dev/.initramfs/usplash_outfifo", O_RDONLY); + if(fifo_fd == -1){ + if(errno != EINTR){ + perror("open"); + an_error_occured = true; + break; + } + if(interrupted_by_signal){ + break; + } + } + }while(fifo_fd == -1); + if(interrupted_by_signal or an_error_occured){ + break; /* Big */ + } + /* Read from FIFO */ - if(not interrupted_by_signal and not an_error_occured){ - int fifo_fd = open("/dev/.initramfs/usplash_outfifo", O_RDONLY); - if(fifo_fd == -1 and not interrupted_by_signal){ - perror("open"); - return EXIT_FAILURE; + size_t buf_allocated = 0; + const size_t blocksize = 1024; + do{ + if(buf_len + blocksize > buf_allocated){ + char *tmp = realloc(buf, buf_allocated + blocksize); + if(tmp == NULL){ + perror("realloc"); + an_error_occured = true; + break; + } + buf = tmp; + buf_allocated += blocksize; } - size_t buf_allocated = 0; - const int blocksize = 1024; do{ - if(buf_len + blocksize > buf_allocated){ - char *tmp = realloc(buf, buf_allocated + blocksize); - if(tmp == NULL){ - perror("realloc"); - an_error_occured = true; - break; - } - buf = tmp; - buf_allocated += blocksize; - } sret = read(fifo_fd, buf + buf_len, buf_allocated - buf_len); if(sret == -1){ - perror("read"); - an_error_occured = true; - break; + if(errno != EINTR){ + perror("read"); + an_error_occured = true; + break; + } + if(interrupted_by_signal){ + break; + } } - buf_len += (size_t)sret; - }while(not interrupted_by_signal and sret != 0); - close(fifo_fd); - } - + }while(sret == -1); + if(interrupted_by_signal or an_error_occured){ + break; + } + + buf_len += (size_t)sret; + }while(sret != 0); + close(fifo_fd); + if(interrupted_by_signal or an_error_occured){ + break; /* Big */ + } + + if(not usplash_write("TIMEOUT", "15") + and (errno != EINTR)){ + perror("usplash_write"); + an_error_occured = true; + } + if(interrupted_by_signal or an_error_occured){ + break; /* Big */ + } + /* Print password to stdout */ - if(not interrupted_by_signal and not an_error_occured){ - size_t written = 0; + size_t written = 0; + do{ do{ sret = write(STDOUT_FILENO, buf + written, buf_len - written); - if(sret == -1 and not interrupted_by_signal){ - perror("write"); - an_error_occured = true; - break; + if(sret == -1){ + if(errno != EINTR){ + perror("write"); + an_error_occured = true; + break; + } + if(interrupted_by_signal){ + break; + } } - written += (size_t)sret; - }while(written < buf_len); - if(not interrupted_by_signal and not an_error_occured){ - return EXIT_SUCCESS; + }while(sret == -1); + if(interrupted_by_signal or an_error_occured){ + break; } + + written += (size_t)sret; + }while(written < buf_len); + if(not interrupted_by_signal and not an_error_occured){ + return EXIT_SUCCESS; } + break; /* Big */ } - kill(usplash_pid, SIGTERM); + /* If we got here, an error or interrupt must have happened */ int cmdline_argc = 0; char **cmdline_argv = malloc(sizeof(char *)); /* Create argv and argc for new usplash*/ { - ptrdiff_t position = 0; - while((size_t)position < cmdline_len){ + size_t position = 0; + while(position < cmdline_len){ char **tmp = realloc(cmdline_argv, (sizeof(char *) * (size_t)(cmdline_argc + 2))); if(tmp == NULL){ @@ -330,25 +415,45 @@ cmdline_argv = tmp; cmdline_argv[cmdline_argc] = cmdline + position; cmdline_argc++; - position = (char *)rawmemchr(cmdline + position, '\0') - - cmdline + 1; + position += strlen(cmdline + position) + 1; } cmdline_argv[cmdline_argc] = NULL; } + /* Kill old usplash */ + kill(usplash_pid, SIGTERM); + sleep(2); + while(kill(usplash_pid, 0) == 0){ + kill(usplash_pid, SIGKILL); + sleep(1); + } pid_t new_usplash_pid = fork(); if(new_usplash_pid == 0){ /* Child; will become new usplash process */ - while(kill(usplash_pid, 0)){ - sleep(2); - kill(usplash_pid, SIGKILL); - sleep(1); + + /* Make the effective user ID (root) the only user ID instead of + the real user ID (mandos) */ + ret = setuid(geteuid()); + if (ret == -1){ + perror("setuid"); } + + setsid(); + ret = chdir("/"); +/* if(fork() != 0){ */ +/* _exit(EXIT_SUCCESS); */ +/* } */ ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace our stdout */ if(ret == -1){ perror("dup2"); _exit(EXIT_FAILURE); } - execv("/sbin/usplash", cmdline_argv); + + execv(usplash_name, cmdline_argv); + } + sleep(2); + if(not usplash_write("PULSATE", NULL) + and (errno != EINTR)){ + perror("usplash_write"); } return EXIT_FAILURE;