/** * Read bytes from a pipe of a forked child process. * In addition, this function makes sure that the child process is ignored * after all data has been read or a fatal error occurred. */ GLOBAL size_t Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen) { ssize_t bytes_read = 0; assert(buffer != NULL); assert(buflen > 0); bytes_read = read(proc->pipe_fd, buffer, buflen); if (bytes_read < 0) { if (errno == EAGAIN) return 0; Log(LOG_CRIT, "Can't read from child process %ld: %s", proc->pid, strerror(errno)); Proc_Close(proc); bytes_read = 0; } else if (bytes_read == 0) { /* EOF: clean up */ LogDebug("Child process %ld: EOF reached, closing pipe.", proc->pid); Proc_Close(proc); } return (size_t)bytes_read; }
/** * Read result of the authenticator sub-process from pipe * * @param r_fd File descriptor of the pipe. * @param events (ignored IO specification) */ static void cb_Read_Auth_Result(int r_fd, UNUSED short events) { char user[CLIENT_USER_LEN], *ptr; CONN_ID conn; CLIENT *client; int result; size_t len; PROC_STAT *proc; LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events); conn = Conn_GetFromProc(r_fd); if (conn == NONE) { /* Ops, none found? Probably the connection has already * been closed!? We'll ignore that ... */ io_close(r_fd); LogDebug("Auth: Got callback for unknown connection!?"); return; } proc = Conn_GetProcStat(conn); client = Conn_GetClient(conn); /* Read result from pipe */ len = Proc_Read(proc, &result, sizeof(result)); Proc_Close(proc); if (len == 0) return; if (len != sizeof(result)) { Log(LOG_CRIT, "Auth: Got malformed result!"); Client_Reject(client, "Internal error", false); return; } if (result == true) { /* Authentication succeeded, now set the correct user name * supplied by the client (without prepended '~' for exmaple), * but cut it at the first '@' character: */ strlcpy(user, Client_OrigUser(client), sizeof(user)); ptr = strchr(user, '@'); if (ptr) *ptr = '\0'; Client_SetUser(client, user, true); (void)Login_User_PostAuth(client); } else Client_Reject(client, "Bad password", false); }