END_TEST START_TEST(test_atomicio_read_from_small_file) { char wbuf[] = "foobar"; ssize_t wsize = strlen(wbuf)+1; ssize_t numwritten; char rbuf[64]; ssize_t numread; errno_t ret; fail_if(atio_fd < 0, "No fd to test?\n"); errno = 0; numwritten = sss_atomic_write_s(atio_fd, wbuf, wsize); ret = errno; fail_unless(ret == 0, "Error %d while writing\n", ret); fail_unless(numwritten == wsize, "Wrote %d bytes expected %d\n", numwritten, wsize); fsync(atio_fd); lseek(atio_fd, 0, SEEK_SET); errno = 0; numread = sss_atomic_read_s(atio_fd, rbuf, 64); ret = errno; fail_unless(ret == 0, "Error %d while reading\n", ret); fail_unless(numread == numwritten, "Read %d bytes expected %d\n", numread, numwritten); }
END_TEST START_TEST(test_atomicio_read_exact_sized_file) { char wbuf[] = "12345678"; ssize_t wsize = strlen(wbuf)+1; ssize_t numwritten; char rbuf[9]; ssize_t numread; errno_t ret; fail_if(atio_fd < 0, "No fd to test?\n"); errno = 0; numwritten = sss_atomic_write_s(atio_fd, wbuf, wsize); ret = errno; fail_unless(ret == 0, "Error %d while writing\n", ret); fail_unless(numwritten == wsize, "Wrote %d bytes expected %d\n", numwritten, wsize); fsync(atio_fd); lseek(atio_fd, 0, SEEK_SET); errno = 0; numread = sss_atomic_read_s(atio_fd, rbuf, 9); ret = errno; fail_unless(ret == 0, "Error %d while reading\n", ret); fail_unless(numread == numwritten, "Read %d bytes expected %d\n", numread, numwritten); fail_unless(rbuf[8] == '\0', "String not NULL terminated?"); fail_unless(strcmp(wbuf, rbuf) == 0, "Read something else than wrote?"); /* We've reached end-of-file, next read must return 0 */ errno = 0; numread = sss_atomic_read_s(atio_fd, rbuf, 9); ret = errno; fail_unless(ret == 0, "Error %d while reading\n", ret); fail_unless(numread == 0, "More data to read?"); }
static int seed_id_input(const char *req, uid_t *_id_input) { char buf[BUFSIZE+1]; size_t len = 0; size_t bytes_read = 0; char *endptr = NULL; int ret = EOK; ret = seed_prompt(req); if (ret != EOK) { return ret; } errno = 0; while ((bytes_read = sss_atomic_read_s(STDIN_FILENO, buf+len, 1)) != 0) { if (bytes_read == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, ("read failed [%d][%s].\n", ret, strerror(ret))); return ret; } if (buf[len] == '\n' || len == BUFSIZE) { buf[len] = '\0'; break; } len += bytes_read; } if (isdigit(*buf)) { errno = 0; *_id_input = (uid_t)strtoll(buf, &endptr, 10); if (errno != 0) { ret = errno; DEBUG(SSSDBG_OP_FAILURE, ("strtoll failed on [%s]: [%d][%s].\n", (char *)buf, ret, strerror(ret))); return ret; } if (*endptr != '\0') { DEBUG(SSSDBG_MINOR_FAILURE, ("extra characters [%s] after ID [%"SPRIuid"]\n", endptr, *_id_input)); } } else { ret = EINVAL; DEBUG(SSSDBG_OP_FAILURE, ("Failed to get %s input.\n", req)); } return ret; }
END_TEST START_TEST(test_atomicio_read_from_empty_file) { char buf[64]; int fd; ssize_t numread; errno_t ret; fd = open("/dev/null", O_RDONLY); fail_if(fd == -1, "Cannot open /dev/null"); errno = 0; numread = sss_atomic_read_s(fd, buf, 64); ret = errno; fail_unless(ret == 0, "Error %d while reading\n", ret); fail_unless(numread == 0, "Read %d bytes expected 0\n", numread); close(fd); }
END_TEST START_TEST(test_atomicio_read_from_large_file) { char wbuf[] = "123456781234567812345678"; ssize_t wsize = strlen(wbuf)+1; ssize_t numwritten; char rbuf[8]; ssize_t numread; ssize_t total; errno_t ret; fail_if(atio_fd < 0, "No fd to test?\n"); errno = 0; numwritten = sss_atomic_write_s(atio_fd, wbuf, wsize); ret = errno; fail_unless(ret == 0, "Error %d while writing\n", ret); fail_unless(numwritten == wsize, "Wrote %d bytes expected %d\n", numwritten, wsize); fsync(atio_fd); lseek(atio_fd, 0, SEEK_SET); total = 0; do { errno = 0; numread = sss_atomic_read_s(atio_fd, rbuf, 8); ret = errno; fail_if(numread == -1, "Read error %d: %s\n", ret, strerror(ret)); total += numread; } while (numread != 0); fail_unless(ret == 0, "Error %d while reading\n", ret); fail_unless(total == numwritten, "Read %d bytes expected %d\n", numread, numwritten); }
static int seed_str_input(TALLOC_CTX *mem_ctx, const char *req, char **_input) { char buf[BUFSIZE+1]; size_t len = 0; size_t bytes_read = 0; int ret = EOK; ret = seed_prompt(req); if (ret != EOK) { return ret; } errno = 0; while ((bytes_read = sss_atomic_read_s(STDIN_FILENO, buf+len, 1)) != 0) { if (bytes_read == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, ("read failed [%d][%s].\n", ret, strerror(ret))); return ret; } if (buf[len] == '\n' || len == BUFSIZE) { buf[len] = '\0'; break; } len += bytes_read; } *_input = talloc_strdup(mem_ctx, buf); if (*_input == NULL) { ret = ENOMEM; DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to allocate input\n")); } return ret; }
int main(int argc, const char *argv[]) { int opt; poptContext pc; int debug_fd = -1; errno_t ret; int sysvol_gpt_version; int result; TALLOC_CTX *main_ctx = NULL; uint8_t *buf = NULL; ssize_t len = 0; struct input_buffer *ibuf = NULL; struct response *resp = NULL; size_t written; struct poptOption long_options[] = { POPT_AUTOHELP {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, _("Debug level"), NULL}, {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0, _("Add debug timestamps"), NULL}, {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0, _("Show timestamps with microseconds"), NULL}, {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0, _("An open file descriptor for the debug logs"), NULL}, {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &debug_to_stderr, 0, _("Send the debug output to stderr directly."), NULL }, POPT_TABLEEND }; /* Set debug level to invalid value so we can decide if -d 0 was used. */ debug_level = SSSDBG_INVALID; pc = poptGetContext(argv[0], argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { default: fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); _exit(-1); } } poptFreeContext(pc); DEBUG_INIT(debug_level); debug_prg_name = talloc_asprintf(NULL, "[sssd[gpo_child[%d]]]", getpid()); if (debug_prg_name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n"); goto fail; } if (debug_fd != -1) { ret = set_debug_file_from_fd(debug_fd); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n"); } } DEBUG(SSSDBG_TRACE_FUNC, "gpo_child started.\n"); main_ctx = talloc_new(NULL); if (main_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n"); talloc_free(discard_const(debug_prg_name)); goto fail; } talloc_steal(main_ctx, debug_prg_name); buf = talloc_size(main_ctx, sizeof(uint8_t)*IN_BUF_SIZE); if (buf == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n"); goto fail; } ibuf = talloc_zero(main_ctx, struct input_buffer); if (ibuf == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); goto fail; } DEBUG(SSSDBG_TRACE_FUNC, "context initialized\n"); errno = 0; len = sss_atomic_read_s(STDIN_FILENO, buf, IN_BUF_SIZE); if (len == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", ret, strerror(ret)); goto fail; } close(STDIN_FILENO); ret = unpack_buffer(buf, len, ibuf); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "unpack_buffer failed.[%d][%s].\n", ret, strerror(ret)); goto fail; } DEBUG(SSSDBG_TRACE_FUNC, "performing smb operations\n"); result = perform_smb_operations(ibuf->cached_gpt_version, ibuf->smb_server, ibuf->smb_share, ibuf->smb_path, ibuf->smb_cse_suffix, &sysvol_gpt_version); if (result != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "perform_smb_operations failed.[%d][%s].\n", result, strerror(result)); goto fail; } ret = prepare_response(main_ctx, sysvol_gpt_version, result, &resp); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "prepare_response failed. [%d][%s].\n", ret, strerror(ret)); goto fail; } errno = 0; written = sss_atomic_write_s(STDOUT_FILENO, resp->buf, resp->size); if (written == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s].\n", ret, strerror(ret)); goto fail; } if (written != resp->size) { DEBUG(SSSDBG_CRIT_FAILURE, "Expected to write %zu bytes, wrote %zu\n", resp->size, written); goto fail; } DEBUG(SSSDBG_TRACE_FUNC, "gpo_child completed successfully\n"); close(STDOUT_FILENO); talloc_free(main_ctx); return EXIT_SUCCESS; fail: DEBUG(SSSDBG_CRIT_FAILURE, "gpo_child failed!\n"); close(STDOUT_FILENO); talloc_free(main_ctx); return EXIT_FAILURE; }
int main(int argc, const char *argv[]) { int ret; int kerr; int opt; int debug_fd = -1; poptContext pc; TALLOC_CTX *main_ctx = NULL; uint8_t *buf = NULL; ssize_t len = 0; const char *ccname = NULL; time_t expire_time = 0; struct input_buffer *ibuf = NULL; struct response *resp = NULL; size_t written; struct poptOption long_options[] = { POPT_AUTOHELP {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, _("Debug level"), NULL}, {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0, _("Add debug timestamps"), NULL}, {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0, _("Show timestamps with microseconds"), NULL}, {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0, _("An open file descriptor for the debug logs"), NULL}, POPT_TABLEEND }; /* Set debug level to invalid value so we can decide if -d 0 was used. */ debug_level = SSSDBG_INVALID; pc = poptGetContext(argv[0], argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { default: fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); _exit(-1); } } poptFreeContext(pc); DEBUG_INIT(debug_level); debug_prg_name = talloc_asprintf(NULL, "[sssd[ldap_child[%d]]]", getpid()); if (!debug_prg_name) { DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf failed.\n")); goto fail; } if (debug_fd != -1) { ret = set_debug_file_from_fd(debug_fd); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("set_debug_file_from_fd failed.\n")); } } DEBUG(SSSDBG_TRACE_FUNC, ("ldap_child started.\n")); main_ctx = talloc_new(NULL); if (main_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n")); talloc_free(discard_const(debug_prg_name)); goto fail; } talloc_steal(main_ctx, debug_prg_name); buf = talloc_size(main_ctx, sizeof(uint8_t)*IN_BUF_SIZE); if (buf == NULL) { DEBUG(1, ("talloc_size failed.\n")); goto fail; } ibuf = talloc_zero(main_ctx, struct input_buffer); if (ibuf == NULL) { DEBUG(1, ("talloc_size failed.\n")); goto fail; } DEBUG(SSSDBG_TRACE_INTERNAL, ("context initialized\n")); errno = 0; len = sss_atomic_read_s(STDIN_FILENO, buf, IN_BUF_SIZE); if (len == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, ("read failed [%d][%s].\n", ret, strerror(ret))); goto fail; } close(STDIN_FILENO); ret = unpack_buffer(buf, len, ibuf); if (ret != EOK) { DEBUG(1, ("unpack_buffer failed.[%d][%s].\n", ret, strerror(ret))); goto fail; } DEBUG(SSSDBG_TRACE_INTERNAL, ("getting TGT sync\n")); kerr = ldap_child_get_tgt_sync(main_ctx, ibuf->realm_str, ibuf->princ_str, ibuf->keytab_name, ibuf->lifetime, &ccname, &expire_time); if (kerr != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("ldap_child_get_tgt_sync failed.\n")); /* Do not return, must report failure */ } ret = prepare_response(main_ctx, ccname, expire_time, kerr, &resp); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("prepare_response failed. [%d][%s].\n", ret, strerror(ret))); goto fail; } errno = 0; written = sss_atomic_write_s(STDOUT_FILENO, resp->buf, resp->size); if (written == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, ("write failed [%d][%s].\n", ret, strerror(ret))); goto fail; } if (written != resp->size) { DEBUG(SSSDBG_CRIT_FAILURE, ("Expected to write %d bytes, wrote %d\n", resp->size, written)); goto fail; } DEBUG(SSSDBG_TRACE_FUNC, ("ldap_child completed successfully\n")); close(STDOUT_FILENO); talloc_free(main_ctx); _exit(0); fail: DEBUG(SSSDBG_CRIT_FAILURE, ("ldap_child failed!\n")); close(STDOUT_FILENO); talloc_free(main_ctx); _exit(-1); }
int pidfile(const char *path, const char *name) { char pid_str[32]; pid_t pid; char *file; int fd; int ret, err; ssize_t len; size_t size; ssize_t written; ssize_t pidlen = sizeof(pid_str) - 1; file = talloc_asprintf(NULL, "%s/%s.pid", path, name); if (!file) { return ENOMEM; } fd = open(file, O_RDONLY, 0644); err = errno; if (fd != -1) { errno = 0; len = sss_atomic_read_s(fd, pid_str, pidlen); ret = errno; if (len == -1) { DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", ret, strerror(ret)); close(fd); talloc_free(file); return EINVAL; } /* Ensure NULL-termination */ pid_str[len] = '\0'; /* let's check the pid */ pid = (pid_t)atoi(pid_str); if (pid != 0) { errno = 0; ret = kill(pid, 0); /* succeeded in signaling the process -> another sssd process */ if (ret == 0) { close(fd); talloc_free(file); return EEXIST; } if (ret != 0 && errno != ESRCH) { err = errno; close(fd); talloc_free(file); return err; } } /* nothing in the file or no process */ close(fd); ret = unlink(file); /* non-fatal failure */ if (ret != EOK) { ret = errno; DEBUG(SSSDBG_MINOR_FAILURE, "Failed to remove file: %s - %d [%s]!\n", file, ret, sss_strerror(ret)); } } else { if (err != ENOENT) { talloc_free(file); return err; } } fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0644); err = errno; if (fd == -1) { talloc_free(file); return err; } talloc_free(file); memset(pid_str, 0, sizeof(pid_str)); snprintf(pid_str, sizeof(pid_str) -1, "%u\n", (unsigned int) getpid()); size = strlen(pid_str); errno = 0; written = sss_atomic_write_s(fd, pid_str, size); if (written == -1) { err = errno; DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s]\n", err, strerror(err)); close(fd); return err; } if (written != size) { DEBUG(SSSDBG_CRIT_FAILURE, "Wrote %zd bytes expected %zu\n", written, size); close(fd); return EIO; } close(fd); return 0; }
int main(int argc, const char *argv[]) { int opt; int debug_fd = -1; poptContext pc; ssize_t len; ssize_t written; errno_t ret; uint8_t buf[IN_BUF_SIZE]; const char *action = NULL; const char *guitar; const char *drums; struct poptOption long_options[] = { POPT_AUTOHELP {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, _("Debug level"), NULL}, {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0, _("Add debug timestamps"), NULL}, {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0, _("Show timestamps with microseconds"), NULL}, {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0, _("An open file descriptor for the debug logs"), NULL}, {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &debug_to_stderr, 0, \ _("Send the debug output to stderr directly."), NULL }, {"guitar", 0, POPT_ARG_STRING, &guitar, 0, _("Who plays guitar"), NULL }, {"drums", 0, POPT_ARG_STRING, &drums, 0, _("Who plays drums"), NULL }, POPT_TABLEEND }; /* Set debug level to invalid value so we can decide if -d 0 was used. */ debug_level = SSSDBG_INVALID; pc = poptGetContext(argv[0], argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { default: fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); poptFreeContext(pc); _exit(1); } } poptFreeContext(pc); action = getenv("TEST_CHILD_ACTION"); if (action) { if (strcasecmp(action, "check_extra_args") == 0) { if (!(strcmp(guitar, "george") == 0 \ && strcmp(drums, "ringo") == 0)) { DEBUG(SSSDBG_CRIT_FAILURE, "This band sounds weird\n"); _exit(1); } } else if (strcasecmp(action, "check_only_extra_args") == 0) { if (debug_timestamps == 1) { DEBUG(SSSDBG_CRIT_FAILURE, "debug_timestamp was passed when only extra args " "should have been\n"); _exit(1); } if (!(strcmp(guitar, "george") == 0 \ && strcmp(drums, "ringo") == 0)) { DEBUG(SSSDBG_CRIT_FAILURE, "This band sounds weird\n"); _exit(1); } } else if (strcasecmp(action, "check_only_extra_args_neg") == 0) { if (debug_timestamps != 1) { DEBUG(SSSDBG_CRIT_FAILURE, "debug_timestamp was not passed as expected\n"); _exit(1); } } else if (strcasecmp(action, "echo") == 0) { errno = 0; len = sss_atomic_read_s(STDIN_FILENO, buf, IN_BUF_SIZE); if (len == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", ret, strerror(ret)); _exit(1); } close(STDIN_FILENO); errno = 0; written = sss_atomic_write_s(3, buf, len); if (written == -1) { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s].\n", ret, strerror(ret)); _exit(1); } close(STDOUT_FILENO); if (written != len) { DEBUG(SSSDBG_CRIT_FAILURE, "Expected to write %zu bytes, wrote %zu\n", len, written); _exit(1); } } } DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n"); _exit(0); }
static errno_t get_uid_from_pid(const pid_t pid, uid_t *uid) { int ret; char path[PATHLEN]; struct stat stat_buf; int fd; char buf[BUFSIZE]; char *p; char *e; char *endptr; uint32_t num=0; errno_t error; ret = snprintf(path, PATHLEN, "/proc/%d/status", pid); if (ret < 0) { DEBUG(SSSDBG_CRIT_FAILURE, "snprintf failed\n"); return EINVAL; } else if (ret >= PATHLEN) { DEBUG(SSSDBG_CRIT_FAILURE, "path too long?!?!\n"); return EINVAL; } fd = open(path, O_RDONLY); if (fd == -1) { error = errno; if (error == ENOENT) { DEBUG(SSSDBG_TRACE_LIBS, "Proc file [%s] is not available anymore, continuing.\n", path); return EOK; } DEBUG(SSSDBG_CRIT_FAILURE, "open failed [%d][%s].\n", error, strerror(error)); return error; } ret = fstat(fd, &stat_buf); if (ret == -1) { error = errno; if (error == ENOENT) { DEBUG(SSSDBG_TRACE_LIBS, "Proc file [%s] is not available anymore, continuing.\n", path); error = EOK; goto fail_fd; } DEBUG(SSSDBG_CRIT_FAILURE, "fstat failed [%d][%s].\n", error, strerror(error)); goto fail_fd; } if (!S_ISREG(stat_buf.st_mode)) { DEBUG(SSSDBG_CRIT_FAILURE, "not a regular file\n"); error = EINVAL; goto fail_fd; } errno = 0; ret = sss_atomic_read_s(fd, buf, BUFSIZE); if (ret == -1) { error = errno; DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", error, strerror(error)); goto fail_fd; } /* Guarantee NULL-termination in case we read the full BUFSIZE somehow */ buf[BUFSIZE-1] = '\0'; ret = close(fd); if (ret == -1) { error = errno; DEBUG(SSSDBG_CRIT_FAILURE, "close failed [%d][%s].\n", error, strerror(error)); } p = strstr(buf, "\nUid:\t"); if (p != NULL) { p += 6; e = strchr(p,'\t'); if (e == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "missing delimiter.\n"); return EINVAL; } else { *e = '\0'; } num = (uint32_t) strtoint32(p, &endptr, 10); error = errno; if (error != 0) { DEBUG(SSSDBG_CRIT_FAILURE, "strtol failed [%s].\n", strerror(error)); return error; } if (*endptr != '\0') { DEBUG(SSSDBG_CRIT_FAILURE, "uid contains extra characters\n"); return EINVAL; } } else { DEBUG(SSSDBG_CRIT_FAILURE, "format error\n"); return EINVAL; } *uid = num; return EOK; fail_fd: close(fd); return error; }
static int seed_password_input_file(TALLOC_CTX *mem_ctx, char *filename, char **_password) { TALLOC_CTX *tmp_ctx = NULL; char *password = NULL; int len = 0; uint8_t buf[PASS_MAX+1]; int fd = -1; int ret = EOK; int valid_i; int i; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("Could not allocate temp context\n")); ret = ENOMEM; goto done; } fd = open(filename, O_RDONLY); if (fd == -1) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to open password file " "[%s] [%d][%s]\n", filename, errno, strerror(errno))); ret = EINVAL; goto done; } errno = 0; len = sss_atomic_read_s(fd, buf, PASS_MAX + 1); if (len == -1) { ret = errno; DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to read password from file " "[%s] [%d][%s]\n", filename, ret, strerror(ret))); close(fd); goto done; } close(fd); if (len > PASS_MAX) { ERROR("Password file too big.\n"); ret = EINVAL; goto done; } buf[len] = '\0'; /* Only the first line is valid (without '\n'). */ for (valid_i = -1; valid_i + 1 < len; valid_i++) { if (buf[valid_i + 1] == '\n') { buf[valid_i + 1] = '\0'; break; } } /* Do not allow empty passwords. */ if (valid_i < 0) { ERROR("Empty passwords are not allowed.\n"); ret = EINVAL; goto done; } /* valid_i is the last valid index of the password followed by \0. * If characters other than \n occur int the rest of the file, it * is an error. */ for (i = valid_i + 2; i < len; i++) { if (buf[i] != '\n') { ERROR("Multi-line passwords are not allowed.\n"); ret = EINVAL; goto done; } } password = talloc_strdup(tmp_ctx, (char *)buf); if (password == NULL) { ret = ENOMEM; goto done; } *_password = talloc_steal(mem_ctx, password); done: talloc_free(tmp_ctx); return ret; }