openpam_readline.c revision 247809
1115619Sdes/*-
2115619Sdes * Copyright (c) 2003 Networks Associates Technology, Inc.
3228690Sdes * Copyright (c) 2004-2011 Dag-Erling Sm��rgrav
4115619Sdes * All rights reserved.
5115619Sdes *
6115619Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and
7115619Sdes * Network Associates Laboratories, the Security Research Division of
8115619Sdes * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
9115619Sdes * ("CBOSS"), as part of the DARPA CHATS research program.
10115619Sdes *
11115619Sdes * Redistribution and use in source and binary forms, with or without
12115619Sdes * modification, are permitted provided that the following conditions
13115619Sdes * are met:
14115619Sdes * 1. Redistributions of source code must retain the above copyright
15115619Sdes *    notice, this list of conditions and the following disclaimer.
16115619Sdes * 2. Redistributions in binary form must reproduce the above copyright
17115619Sdes *    notice, this list of conditions and the following disclaimer in the
18115619Sdes *    documentation and/or other materials provided with the distribution.
19115619Sdes * 3. The name of the author may not be used to endorse or promote
20115619Sdes *    products derived from this software without specific prior written
21115619Sdes *    permission.
22115619Sdes *
23115619Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24115619Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25115619Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26115619Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27115619Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28115619Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29115619Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30115619Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31115619Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32115619Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33115619Sdes * SUCH DAMAGE.
34115619Sdes *
35236099Sdes * $Id: openpam_readline.c 596 2012-04-14 14:52:40Z des $
36115619Sdes */
37115619Sdes
38228690Sdes#ifdef HAVE_CONFIG_H
39228690Sdes# include "config.h"
40228690Sdes#endif
41228690Sdes
42115619Sdes#include <ctype.h>
43115619Sdes#include <stdio.h>
44115619Sdes#include <stdlib.h>
45115619Sdes
46115619Sdes#include <security/pam_appl.h>
47236099Sdes
48115619Sdes#include "openpam_impl.h"
49115619Sdes
50115619Sdes#define MIN_LINE_LENGTH 128
51115619Sdes
52115619Sdes/*
53115619Sdes * OpenPAM extension
54115619Sdes *
55115619Sdes * Read a line from a file.
56115619Sdes */
57115619Sdes
58115619Sdeschar *
59115619Sdesopenpam_readline(FILE *f, int *lineno, size_t *lenp)
60115619Sdes{
61168463Sdes	char *line;
62115619Sdes	size_t len, size;
63115619Sdes	int ch;
64115619Sdes
65247809Sdes	line = NULL;
66247809Sdes	if (openpam_straddch(&line, &size, &len, 0) != 0)
67115619Sdes		return (NULL);
68115619Sdes	for (;;) {
69115619Sdes		ch = fgetc(f);
70115619Sdes		/* strip comment */
71115619Sdes		if (ch == '#') {
72115619Sdes			do {
73115619Sdes				ch = fgetc(f);
74115619Sdes			} while (ch != EOF && ch != '\n');
75115619Sdes		}
76115619Sdes		/* eof */
77115619Sdes		if (ch == EOF) {
78228690Sdes			/* done */
79115619Sdes			break;
80115619Sdes		}
81115619Sdes		/* eol */
82115619Sdes		if (ch == '\n') {
83115619Sdes			if (lineno != NULL)
84115619Sdes				++*lineno;
85115619Sdes			/* skip blank lines */
86115619Sdes			if (len == 0)
87115619Sdes				continue;
88115619Sdes			/* continuation */
89115619Sdes			if (line[len - 1] == '\\') {
90115619Sdes				line[--len] = '\0';
91228690Sdes				continue;
92115619Sdes			}
93228690Sdes			/* done */
94228690Sdes			break;
95115619Sdes		}
96115619Sdes		/* anything else */
97236099Sdes		if (openpam_straddch(&line, &size, &len, ch) != 0)
98236099Sdes			goto fail;
99115619Sdes	}
100228690Sdes	if (len == 0)
101228690Sdes		goto fail;
102115619Sdes	if (lenp != NULL)
103115619Sdes		*lenp = len;
104236099Sdes	openpam_log(PAM_LOG_LIBDEBUG, "returning '%s'", line);
105115619Sdes	return (line);
106228690Sdesfail:
107115619Sdes	FREE(line);
108115619Sdes	return (NULL);
109115619Sdes}
110115619Sdes
111115619Sdes/**
112236099Sdes * DEPRECATED openpam_readlinev
113236099Sdes *
114115619Sdes * The =openpam_readline function reads a line from a file, and returns it
115236099Sdes * in a NUL-terminated buffer allocated with =!malloc.
116115619Sdes *
117115619Sdes * The =openpam_readline function performs a certain amount of processing
118228690Sdes * on the data it reads:
119115619Sdes *
120236099Sdes *  - Comments (introduced by a hash sign) are stripped.
121236099Sdes *
122228690Sdes *  - Blank lines are ignored.
123236099Sdes *
124228690Sdes *  - If a line ends in a backslash, the backslash is stripped and the
125228690Sdes *    next line is appended.
126228690Sdes *
127115619Sdes * If =lineno is not =NULL, the integer variable it points to is
128115619Sdes * incremented every time a newline character is read.
129115619Sdes *
130115619Sdes * If =lenp is not =NULL, the length of the line (not including the
131115619Sdes * terminating NUL character) is stored in the variable it points to.
132115619Sdes *
133115619Sdes * The caller is responsible for releasing the returned buffer by passing
134236099Sdes * it to =!free.
135236099Sdes *
136236099Sdes * >openpam_readlinev
137236099Sdes * >openpam_readword
138115619Sdes */
139