1236099Sdes/*- 2348980Sdes * Copyright (c) 2012-2017 Dag-Erling Sm��rgrav 3236099Sdes * All rights reserved. 4236099Sdes * 5236099Sdes * Redistribution and use in source and binary forms, with or without 6236099Sdes * modification, are permitted provided that the following conditions 7236099Sdes * are met: 8236099Sdes * 1. Redistributions of source code must retain the above copyright 9255376Sdes * notice, this list of conditions and the following disclaimer. 10236099Sdes * 2. Redistributions in binary form must reproduce the above copyright 11236099Sdes * notice, this list of conditions and the following disclaimer in the 12236099Sdes * documentation and/or other materials provided with the distribution. 13236099Sdes * 3. The name of the author may not be used to endorse or promote 14236099Sdes * products derived from this software without specific prior written 15236099Sdes * permission. 16236099Sdes * 17236099Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18236099Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19236099Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20236099Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21236099Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22236099Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23236099Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24236099Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25236099Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26236099Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27236099Sdes * SUCH DAMAGE. 28236099Sdes * 29348980Sdes * $OpenPAM: t_openpam_readlinev.c 938 2017-04-30 21:34:42Z des $ 30236099Sdes */ 31236099Sdes 32236099Sdes#ifdef HAVE_CONFIG_H 33236099Sdes# include "config.h" 34236099Sdes#endif 35236099Sdes 36236099Sdes#include <err.h> 37348980Sdes#include <stdint.h> 38236099Sdes#include <stdio.h> 39236099Sdes#include <stdlib.h> 40236099Sdes#include <string.h> 41236099Sdes 42348980Sdes#include <cryb/test.h> 43348980Sdes 44236099Sdes#include <security/pam_appl.h> 45236099Sdes#include <security/openpam.h> 46236099Sdes 47236099Sdes#include "openpam_impl.h" 48236099Sdes 49348980Sdes#define T_FUNC(n, d) \ 50348980Sdes static const char *t_ ## n ## _desc = d; \ 51348980Sdes static int t_ ## n ## _func(OPENPAM_UNUSED(char **desc), \ 52348980Sdes OPENPAM_UNUSED(void *arg)) 53348980Sdes 54348980Sdes#define T(n) \ 55348980Sdes t_add_test(&t_ ## n ## _func, NULL, "%s", t_ ## n ## _desc) 56348980Sdes 57236099Sdes/* 58236099Sdes * Read a line from the temp file and verify that the result matches our 59236099Sdes * expectations: whether a line was read at all, how many and which words 60236099Sdes * it contained, how many lines were read (in case of quoted or escaped 61236099Sdes * newlines) and whether we reached the end of the file. 62236099Sdes */ 63236099Sdesstatic int 64255376Sdesorlv_expect(struct t_file *tf, const char **expectedv, int lines, int eof) 65236099Sdes{ 66236099Sdes int expectedc, gotc, i, lineno = 0; 67236099Sdes char **gotv; 68348980Sdes int ret; 69236099Sdes 70348980Sdes ret = 1; 71236099Sdes expectedc = 0; 72236099Sdes if (expectedv != NULL) 73236099Sdes while (expectedv[expectedc] != NULL) 74236099Sdes ++expectedc; 75255376Sdes gotv = openpam_readlinev(tf->file, &lineno, &gotc); 76255376Sdes if (t_ferror(tf)) 77255376Sdes err(1, "%s(): %s", __func__, tf->name); 78236099Sdes if (expectedv != NULL && gotv == NULL) { 79348980Sdes t_printv("expected %d words, got nothing\n", expectedc); 80348980Sdes ret = 0; 81348980Sdes } else if (expectedv == NULL && gotv != NULL) { 82348980Sdes t_printv("expected nothing, got %d words\n", gotc); 83348980Sdes ret = 0; 84348980Sdes } else if (expectedv != NULL && gotv != NULL) { 85236099Sdes if (expectedc != gotc) { 86348980Sdes t_printv("expected %d words, got %d\n", 87236099Sdes expectedc, gotc); 88348980Sdes ret = 0; 89236099Sdes } 90236099Sdes for (i = 0; i < gotc; ++i) { 91236099Sdes if (strcmp(expectedv[i], gotv[i]) != 0) { 92348980Sdes t_printv("word %d: expected <<%s>>, " 93236099Sdes "got <<%s>>\n", i, expectedv[i], gotv[i]); 94348980Sdes ret = 0; 95236099Sdes } 96236099Sdes } 97236099Sdes } 98348980Sdes FREEV(gotc, gotv); 99236099Sdes if (lineno != lines) { 100348980Sdes t_printv("expected to advance %d lines, advanced %d lines\n", 101236099Sdes lines, lineno); 102348980Sdes ret = 0; 103236099Sdes } 104255376Sdes if (eof && !t_feof(tf)) { 105348980Sdes t_printv("expected EOF, but didn't get it\n"); 106348980Sdes ret = 0; 107348980Sdes } else if (!eof && t_feof(tf)) { 108348980Sdes t_printv("didn't expect EOF, but got it anyway\n"); 109348980Sdes ret = 0; 110236099Sdes } 111348980Sdes return (ret); 112236099Sdes} 113236099Sdes 114236099Sdes 115236099Sdes/*************************************************************************** 116236099Sdes * Commonly-used lines 117236099Sdes */ 118236099Sdes 119236099Sdesstatic const char *empty[] = { 120236099Sdes NULL 121236099Sdes}; 122236099Sdes 123236099Sdesstatic const char *hello[] = { 124236099Sdes "hello", 125236099Sdes NULL 126236099Sdes}; 127236099Sdes 128236099Sdesstatic const char *hello_world[] = { 129236099Sdes "hello", 130236099Sdes "world", 131236099Sdes NULL 132236099Sdes}; 133236099Sdes 134348980Sdesstatic const char *numbers[] = { 135348980Sdes "zero", "one", "two", "three", "four", "five", "six", "seven", 136348980Sdes "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", 137348980Sdes "fifteen", "sixteen", "seventeen", "nineteen", "twenty", 138348980Sdes "twenty-one", "twenty-two", "twenty-three", "twenty-four", 139348980Sdes "twenty-five", "twenty-six", "twenty-seven", "twenty-eight", 140348980Sdes "twenty-nine", "thirty", "thirty-one", "thirty-two", "thirty-three", 141348980Sdes "thirty-four", "thirty-five", "thirty-six", "thirty-seven", 142348980Sdes "thirty-eight", "thirty-nine", "fourty", "fourty-one", "fourty-two", 143348980Sdes "fourty-three", "fourty-four", "fourty-five", "fourty-six", 144348980Sdes "fourty-seven", "fourty-eight", "fourty-nine", "fifty", "fifty-one", 145348980Sdes "fifty-two", "fifty-three", "fifty-four", "fifty-five", "fifty-six", 146348980Sdes "fifty-seven", "fifty-eight", "fifty-nine", "sixty", "sixty-one", 147348980Sdes "sixty-two", "sixty-three", 148348980Sdes NULL 149348980Sdes}; 150348980Sdes 151236099Sdes 152236099Sdes/*************************************************************************** 153236099Sdes * Lines without words 154236099Sdes */ 155236099Sdes 156236099SdesT_FUNC(empty_input, "empty input") 157236099Sdes{ 158255376Sdes struct t_file *tf; 159236099Sdes int ret; 160236099Sdes 161255376Sdes tf = t_fopen(NULL); 162255376Sdes ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 163255376Sdes t_fclose(tf); 164236099Sdes return (ret); 165236099Sdes} 166236099Sdes 167236099SdesT_FUNC(empty_line, "empty line") 168236099Sdes{ 169255376Sdes struct t_file *tf; 170236099Sdes int ret; 171236099Sdes 172255376Sdes tf = t_fopen(NULL); 173255376Sdes t_fprintf(tf, "\n"); 174255376Sdes t_frewind(tf); 175255376Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 176255376Sdes t_fclose(tf); 177236099Sdes return (ret); 178236099Sdes} 179236099Sdes 180236099SdesT_FUNC(unterminated_empty_line, "unterminated empty line") 181236099Sdes{ 182255376Sdes struct t_file *tf; 183236099Sdes int ret; 184236099Sdes 185255376Sdes tf = t_fopen(NULL); 186255376Sdes t_fprintf(tf, " "); 187255376Sdes t_frewind(tf); 188255376Sdes ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 189255376Sdes t_fclose(tf); 190236099Sdes return (ret); 191236099Sdes} 192236099Sdes 193236099SdesT_FUNC(whitespace, "whitespace") 194236099Sdes{ 195255376Sdes struct t_file *tf; 196236099Sdes int ret; 197236099Sdes 198255376Sdes tf = t_fopen(NULL); 199255376Sdes t_fprintf(tf, " \n"); 200255376Sdes t_frewind(tf); 201255376Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 202255376Sdes t_fclose(tf); 203236099Sdes return (ret); 204236099Sdes} 205236099Sdes 206236099SdesT_FUNC(comment, "comment") 207236099Sdes{ 208255376Sdes struct t_file *tf; 209236099Sdes int ret; 210236099Sdes 211255376Sdes tf = t_fopen(NULL); 212255376Sdes t_fprintf(tf, "# comment\n"); 213255376Sdes t_frewind(tf); 214255376Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 215255376Sdes t_fclose(tf); 216236099Sdes return (ret); 217236099Sdes} 218236099Sdes 219236099SdesT_FUNC(whitespace_before_comment, "whitespace before comment") 220236099Sdes{ 221255376Sdes struct t_file *tf; 222236099Sdes int ret; 223236099Sdes 224255376Sdes tf = t_fopen(NULL); 225255376Sdes t_fprintf(tf, " # comment\n"); 226255376Sdes t_frewind(tf); 227255376Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 228255376Sdes t_fclose(tf); 229236099Sdes return (ret); 230236099Sdes} 231236099Sdes 232348980SdesT_FUNC(line_continuation_within_whitespace, "line continuation within whitespace") 233348980Sdes{ 234348980Sdes struct t_file *tf; 235348980Sdes int ret; 236348980Sdes 237348980Sdes tf = t_fopen(NULL); 238348980Sdes t_fprintf(tf, "%s \\\n %s\n", hello_world[0], hello_world[1]); 239348980Sdes t_frewind(tf); 240348980Sdes ret = orlv_expect(tf, hello_world, 2 /*lines*/, 0 /*eof*/) && 241348980Sdes orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 242348980Sdes t_fclose(tf); 243348980Sdes return (ret); 244348980Sdes} 245348980Sdes 246236099Sdes 247236099Sdes/*************************************************************************** 248236099Sdes * Simple words 249236099Sdes */ 250236099Sdes 251236099SdesT_FUNC(one_word, "one word") 252236099Sdes{ 253255376Sdes struct t_file *tf; 254236099Sdes int ret; 255236099Sdes 256255376Sdes tf = t_fopen(NULL); 257255376Sdes t_fprintf(tf, "hello\n"); 258255376Sdes t_frewind(tf); 259255376Sdes ret = orlv_expect(tf, hello, 1 /*lines*/, 0 /*eof*/); 260255376Sdes t_fclose(tf); 261236099Sdes return (ret); 262236099Sdes} 263236099Sdes 264236099SdesT_FUNC(two_words, "two words") 265236099Sdes{ 266255376Sdes struct t_file *tf; 267236099Sdes int ret; 268236099Sdes 269255376Sdes tf = t_fopen(NULL); 270255376Sdes t_fprintf(tf, "hello world\n"); 271255376Sdes t_frewind(tf); 272255376Sdes ret = orlv_expect(tf, hello_world, 1 /*lines*/, 0 /*eof*/); 273255376Sdes t_fclose(tf); 274236099Sdes return (ret); 275236099Sdes} 276236099Sdes 277348980SdesT_FUNC(many_words, "many words") 278348980Sdes{ 279348980Sdes struct t_file *tf; 280348980Sdes const char **word; 281348980Sdes int ret; 282348980Sdes 283348980Sdes tf = t_fopen(NULL); 284348980Sdes for (word = numbers; *word; ++word) 285348980Sdes t_fprintf(tf, " %s", *word); 286348980Sdes t_fprintf(tf, "\n"); 287348980Sdes t_frewind(tf); 288348980Sdes ret = orlv_expect(tf, numbers, 1 /*lines*/, 0 /*eof*/); 289348980Sdes t_fclose(tf); 290348980Sdes return (ret); 291348980Sdes} 292348980Sdes 293236099SdesT_FUNC(unterminated_line, "unterminated line") 294236099Sdes{ 295255376Sdes struct t_file *tf; 296236099Sdes int ret; 297236099Sdes 298255376Sdes tf = t_fopen(NULL); 299255376Sdes t_fprintf(tf, "hello world"); 300255376Sdes t_frewind(tf); 301255376Sdes ret = orlv_expect(tf, hello_world, 0 /*lines*/, 1 /*eof*/); 302255376Sdes t_fclose(tf); 303236099Sdes return (ret); 304236099Sdes} 305236099Sdes 306236099Sdes 307236099Sdes/*************************************************************************** 308236099Sdes * Boilerplate 309236099Sdes */ 310236099Sdes 311348980Sdesstatic int 312236099Sdest_prepare(int argc, char *argv[]) 313236099Sdes{ 314236099Sdes 315236099Sdes (void)argc; 316236099Sdes (void)argv; 317348980Sdes 318348980Sdes T(empty_input); 319348980Sdes T(empty_line); 320348980Sdes T(unterminated_empty_line); 321348980Sdes T(whitespace); 322348980Sdes T(comment); 323348980Sdes T(whitespace_before_comment); 324348980Sdes T(line_continuation_within_whitespace); 325348980Sdes 326348980Sdes T(one_word); 327348980Sdes T(two_words); 328348980Sdes T(many_words); 329348980Sdes T(unterminated_line); 330348980Sdes 331348980Sdes return (0); 332236099Sdes} 333236099Sdes 334348980Sdesint 335348980Sdesmain(int argc, char *argv[]) 336236099Sdes{ 337348980Sdes 338348980Sdes t_main(t_prepare, NULL, argc, argv); 339236099Sdes} 340