示例#1
0
/*
 * Read a line from the temp file and verify that the result matches our
 * expectations: whether a line was read at all, how many and which words
 * it contained, how many lines were read (in case of quoted or escaped
 * newlines) and whether we reached the end of the file.
 */
static int
orlv_expect(const char **expectedv, int lines, int eof)
{
	int expectedc, gotc, i, lineno = 0;
	char **gotv;

	expectedc = 0;
	if (expectedv != NULL)
		while (expectedv[expectedc] != NULL)
			++expectedc;
	gotv = openpam_readlinev(f, &lineno, &gotc);
	if (ferror(f))
		err(1, "%s(): %s", __func__, filename);
	if (expectedv != NULL && gotv == NULL) {
		t_verbose("expected %d words, got nothing\n", expectedc);
		return (0);
	}
	if (expectedv == NULL && gotv != NULL) {
		t_verbose("expected nothing, got %d words\n", gotc);
		FREEV(gotc, gotv);
		return (0);
	}
	if (expectedv != NULL && gotv != NULL) {
		if (expectedc != gotc) {
			t_verbose("expected %d words, got %d\n",
			    expectedc, gotc);
			FREEV(gotc, gotv);
			return (0);
		}
		for (i = 0; i < gotc; ++i) {
			if (strcmp(expectedv[i], gotv[i]) != 0) {
				t_verbose("word %d: expected <<%s>>, "
				    "got <<%s>>\n", i, expectedv[i], gotv[i]);
				FREEV(gotc, gotv);
				return (0);
			}
		}
		FREEV(gotc, gotv);
	}
	if (lineno != lines) {
		t_verbose("expected to advance %d lines, advanced %d lines\n",
		    lines, lineno);
		return (0);
	}
	if (eof && !feof(f)) {
		t_verbose("expected EOF, but didn't get it\n");
		return (0);
	}
	if (!eof && feof(f)) {
		t_verbose("didn't expect EOF, but got it anyway\n");
		return (0);
	}
	return (1);
}
示例#2
0
void
write_ticket(const char* user, const char* data)
{
    int fd, ret, word_count;
    FILE *f, *t;
    char **words;

    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);

    if ((fd = open_ticket(O_RDWR|O_CREAT|O_EXLOCK)) < 0 ||
            (f = fdopen(fd, "r")) == NULL) {
        if (fd >= 0)
            close(fd);
        return;
    }

    char temp_path[strlen(AUTH_TICKET_PATH) + 7 + 1];
    if (sprintf(temp_path, "%s.XXXXXX", AUTH_TICKET_PATH) < 0)
        goto done;

    if ((ret = mkstemp(temp_path)) == -1 ||
            (t = fopen(temp_path, "w")) == NULL) {
        if (ret != -1)
            unlink(temp_path);
        goto done;
    }

    ret = 0;
    while ((words = openpam_readlinev(f, NULL, &word_count)) != NULL) {
        if (word_count == 3 && strcmp(user, words[0]) != 0)
            ret = fprintf(t, "%s %s %s\n",
                          words[0], words[1], words[2]);
        for(int i = 0; i < word_count; i++)
            free(words[i]);
        free(words);
        if (ret < 0)
            break;
    }
    if (ret >= 0)
        ret = fprintf(t, "%s %s %d\n", user, data, (int)now.tv_sec);

    if (fclose(t) == 0) {
        if (ret >= 0 && rename(temp_path, AUTH_TICKET_PATH) == 0) {
            ftruncate(fd, 0);
            goto done;
        }
    }
    truncate(temp_path, 0);
    unlink(temp_path);
done:
    fclose(f);
}
示例#3
0
static bool
read_ticket(const char *user, int *timestamp, char **password)
{
    int fd, word_count;
    FILE *f;
    char **words;
    bool success = false;

    if ((fd = open_ticket(O_RDONLY|O_SHLOCK)) < 0 ||
            (f = fdopen(fd, "r")) == NULL) {
        if (fd >= 0)
            close(fd);
        return (false);
    }

    words = openpam_readlinev(f, NULL, &word_count);
    while (words != NULL) {
        if (word_count != 3 || strcmp(user, words[0]) != 0) {
            for(int i = 0; i < word_count; i++) {
                free(words[i]);
            }
            free(words);
            words = openpam_readlinev(f, NULL, &word_count);
            continue;
        }

        *password = words[1];
        const char *err;
        *timestamp = strtonum(words[2], 0, INT_MAX - TIMEOUT, &err);
        success = (err == NULL);

        free(words[0]);
        free(words[2]);
        free(words);
        words = NULL;
    }
    fclose(f);
    return (success);
}
示例#4
0
/*
 * Extracts given chains from a policy file.
 *
 * Returns the number of policy entries which were found for the specified
 * service and facility, or -1 if a system error occurred or a syntax
 * error was encountered.
 */
static int
openpam_parse_chain(pam_handle_t *pamh,
	const char *service,
	pam_facility_t facility,
	FILE *f,
	const char *filename,
	openpam_style_t style)
{
	pam_chain_t *this, **next;
	pam_facility_t fclt;
	pam_control_t ctlf;
	char *name, *servicename, *modulename;
	int count, lineno, ret, serrno;
	char **wordv, *word;
	int i, wordc;

	count = 0;
	this = NULL;
	name = NULL;
	lineno = 0;
	wordc = 0;
	wordv = NULL;
	while ((wordv = openpam_readlinev(f, &lineno, &wordc)) != NULL) {
		/* blank line? */
		if (wordc == 0) {
			FREEV(wordc, wordv);
			continue;
		}
		i = 0;

		/* check service name if necessary */
		if (style == pam_conf_style &&
		    strcmp(wordv[i++], service) != 0) {
			FREEV(wordc, wordv);
			continue;
		}

		/* check facility name */
		if ((word = wordv[i++]) == NULL ||
		    (fclt = parse_facility_name(word)) == (pam_facility_t)-1) {
			openpam_log(PAM_LOG_ERROR,
			    "%s(%d): missing or invalid facility",
			    filename, lineno);
			errno = EINVAL;
			goto fail;
		}
		if (facility != fclt && facility != PAM_FACILITY_ANY) {
			FREEV(wordc, wordv);
			continue;
		}

		/* check for "include" */
		if ((word = wordv[i++]) != NULL &&
		    strcmp(word, "include") == 0) {
			if ((servicename = wordv[i++]) == NULL ||
			    !valid_service_name(servicename)) {
				openpam_log(PAM_LOG_ERROR,
				    "%s(%d): missing or invalid service name",
				    filename, lineno);
				errno = EINVAL;
				goto fail;
			}
			if (wordv[i] != NULL) {
				openpam_log(PAM_LOG_ERROR,
				    "%s(%d): garbage at end of line",
				    filename, lineno);
				errno = EINVAL;
				goto fail;
			}
			ret = openpam_load_chain(pamh, servicename, fclt);
			FREEV(wordc, wordv);
			if (ret < 0) {
				/*
				 * Bogus errno, but this ensures that the
				 * outer loop does not just ignore the
				 * error and keep searching.
				 */
				if (errno == ENOENT)
					errno = EINVAL;
				goto fail;
			}
			continue;
		}

		/* get control flag */
		if (word == NULL || /* same word we compared to "include" */
		    (ctlf = parse_control_flag(word)) == (pam_control_t)-1) {
			openpam_log(PAM_LOG_ERROR,
			    "%s(%d): missing or invalid control flag",
			    filename, lineno);
			errno = EINVAL;
			goto fail;
		}

		/* get module name */
		if ((modulename = wordv[i++]) == NULL ||
		    !valid_module_name(modulename)) {
			openpam_log(PAM_LOG_ERROR,
			    "%s(%d): missing or invalid module name",
			    filename, lineno);
			errno = EINVAL;
			goto fail;
		}

		/* allocate new entry */
		if ((this = calloc(1, sizeof *this)) == NULL)
			goto syserr;
		this->flag = ctlf;

		/* load module */
		if ((this->module = openpam_load_module(modulename)) == NULL) {
			if (errno == ENOENT)
				errno = ENOEXEC;
			goto fail;
		}

		/*
		 * The remaining items in wordv are the module's
		 * arguments.  We could set this->optv = wordv + i, but
		 * then free(this->optv) wouldn't work.  Instead, we free
		 * the words we've already consumed, shift the rest up,
		 * and clear the tail end of the array.
		 */
		this->optc = wordc - i;
		for (i = 0; i < wordc - this->optc; ++i) {
			FREE(wordv[i]);
		}
		for (i = 0; i < this->optc; ++i) {
			wordv[i] = wordv[wordc - this->optc + i];
			wordv[wordc - this->optc + i] = NULL;
		}
		this->optv = wordv;
		wordv = NULL;
		wordc = 0;

		/* hook it up */
		for (next = &pamh->chains[fclt]; *next != NULL;
		     next = &(*next)->next)
			/* nothing */ ;
		*next = this;
		this = NULL;
		++count;
	}
	/*
	 * The loop ended because openpam_readword() returned NULL, which
	 * can happen for four different reasons: an I/O error (ferror(f)
	 * is true), a memory allocation failure (ferror(f) is false,
	 * feof(f) is false, errno is non-zero), the file ended with an
	 * unterminated quote or backslash escape (ferror(f) is false,
	 * feof(f) is true, errno is non-zero), or the end of the file was
	 * reached without error (ferror(f) is false, feof(f) is true,
	 * errno is zero).
	 */
	if (ferror(f) || errno != 0)
		goto syserr;
	if (!feof(f))
		goto fail;
	fclose(f);
	return (count);
syserr:
	serrno = errno;
	openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
	errno = serrno;
	/* fall through */
fail:
	serrno = errno;
	if (this && this->optc && this->optv)
		FREEV(this->optc, this->optv);
	FREE(this);
	FREEV(wordc, wordv);
	FREE(wordv);
	FREE(name);
	fclose(f);
	errno = serrno;
	return (-1);
}