utils.c
1 /*- 2 * Copyright (c) 2022 Baptiste Daroussin <bapt@FreeBSD.org> 3 *~ 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer 9 * in this position and unchanged. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 *~ 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <atf-c.h> 27 #include <atf-c/macros.h> 28 #include <err.h> 29 #include <fcntl.h> 30 #include <private/utils.h> 31 #include <private/add.h> 32 33 ATF_TC_WITHOUT_HEAD(hidden_tempfile); 34 ATF_TC_WITHOUT_HEAD(random_suffix); 35 ATF_TC_WITHOUT_HEAD(json_escape); 36 ATF_TC_WITHOUT_HEAD(open_tempdir); 37 ATF_TC_WITHOUT_HEAD(get_http_auth); 38 ATF_TC_WITHOUT_HEAD(str_ends_with); 39 ATF_TC_WITHOUT_HEAD(match_paths); 40 41 ATF_TC_BODY(hidden_tempfile, tc) { 42 const char *filename = "plop"; 43 const char *longfile = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif"; 44 const char *pathfn = "/tmp/plop"; 45 const char *pathlongfn = "/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif"; 46 char buf[MAXPATHLEN]; 47 48 hidden_tempfile(buf, MAXPATHLEN, filename); 49 ATF_REQUIRE_EQ_MSG(strncmp(buf, ".pkgtemp.plop.", 14), 0, "bad filename '%s'", buf); 50 hidden_tempfile(buf, MAXPATHLEN, longfile); 51 ATF_REQUIRE_EQ_MSG(strncmp(buf, ".AAA", 4), 0, "bad filename '%s'", buf); 52 53 hidden_tempfile(buf, MAXPATHLEN, pathfn); 54 ATF_REQUIRE_EQ_MSG(strncmp(buf, "/tmp/.pkgtemp.plop.", 19), 0, "bad filename '%s'", buf); 55 56 hidden_tempfile(buf, MAXPATHLEN, pathlongfn); 57 ATF_REQUIRE_EQ_MSG(strncmp(buf, "/tmp/.AAA", 9), 0, "bad filename '%s'", buf); 58 59 60 } 61 ATF_TC_BODY(random_suffix, tc) { 62 char buf[14]; 63 64 buf[0] = '\0'; 65 append_random_suffix(buf, sizeof(buf), 12); 66 ATF_REQUIRE_EQ_MSG(strlen(buf), 13, "suffix not long enough %lu", strlen(buf)); 67 snprintf(buf, sizeof(buf), "filename"); 68 append_random_suffix(buf, sizeof(buf), 12); 69 ATF_REQUIRE_EQ_MSG(strlen(buf), 13, "suffix not long enough %lu", strlen(buf)); 70 } 71 72 ATF_TC_BODY(json_escape, tc) { 73 char *m = json_escape("entry1\"\"\\ "); 74 ATF_REQUIRE_STREQ_MSG(m, "entry1\\\"\\\"\\\\ ", "Invalid escaping"); 75 free(m); 76 } 77 78 ATF_TC_BODY(open_tempdir, tc) { 79 struct pkg_add_context ctx = { 0 }; 80 struct tempdir *t; 81 ctx.rootfd = open(getenv("TMPDIR"), O_DIRECTORY); 82 ATF_REQUIRE_MSG(ctx.rootfd != -1, "impossible to open TMPDIR"); 83 t = open_tempdir(&ctx, "/plop"); 84 ATF_REQUIRE(t == NULL); 85 mkdirat(ctx.rootfd, "usr", 0755); 86 t = open_tempdir(&ctx, "/usr/local/directory"); 87 ATF_REQUIRE(t != NULL); 88 ATF_REQUIRE_STREQ(t->name, "/usr/local"); 89 ATF_REQUIRE_EQ(t->len, strlen("/usr/local")); 90 ATF_REQUIRE(strncmp(t->temp, "/usr/.pkgtemp.", 14) == 0); 91 ATF_REQUIRE(t->fd != -1); 92 close(t->fd); 93 free(t); 94 t = open_tempdir(&ctx, "/nousr/local/directory"); 95 ATF_REQUIRE(t != NULL); 96 ATF_REQUIRE_STREQ(t->name, "/nousr"); 97 ATF_REQUIRE_EQ(t->len, strlen("/nousr")); 98 ATF_REQUIRE(strncmp(t->temp, "/.pkgtemp.", 10) == 0); 99 ATF_REQUIRE(t->fd != -1); 100 close(t->fd); 101 free(t); 102 mkdirat(ctx.rootfd, "dir", 0755); 103 /* a file in the path */ 104 close(openat(ctx.rootfd, "dir/file1", O_CREAT|O_WRONLY, 0644)); 105 t = open_tempdir(&ctx, "/dir/file1/test"); 106 ATF_REQUIRE(t != NULL); 107 ATF_REQUIRE_STREQ(t->name, "/dir/file1"); 108 ATF_REQUIRE_EQ(t->len, strlen("/dir/file1")); 109 ATF_REQUIRE(strncmp(t->temp, "/dir/.pkgtemp.", 14) == 0); 110 ATF_REQUIRE(t->fd != -1); 111 close(t->fd); 112 free(t); 113 } 114 115 ATF_TC_BODY(get_http_auth, tc) { 116 unsetenv("HTTP_AUTH"); 117 ATF_REQUIRE(get_http_auth() == NULL); 118 setenv("HTTP_AUTH", "plop", 1); 119 ATF_REQUIRE(get_http_auth() == NULL); 120 121 setenv("HTTP_AUTH", "basic:any", 1); 122 ATF_REQUIRE(get_http_auth() == NULL); 123 124 setenv("HTTP_AUTH", "basic:any:user", 1); 125 ATF_REQUIRE(get_http_auth() == NULL); 126 127 setenv("HTTP_AUTH", "basic:any:user:passwd", 1); 128 ATF_REQUIRE_STREQ(get_http_auth(), "user:passwd"); 129 } 130 131 ATF_TC_BODY(str_ends_with, tc) { 132 ATF_REQUIRE(str_ends_with(NULL, NULL)); 133 ATF_REQUIRE(!str_ends_with(NULL, "end")); 134 ATF_REQUIRE(!str_ends_with("a", "end")); 135 ATF_REQUIRE(str_ends_with("end", "end")); 136 ATF_REQUIRE(str_ends_with("backend", "end")); 137 } 138 139 ATF_TC_BODY(match_paths, tc) { 140 const char *paths[] = { 141 "////", 142 "/foo1", 143 "/foo2/", 144 "////foo3/bar", 145 "/foo4//bar", 146 "/foo5//////bar", 147 "//foo6//bar/", 148 "/foo7//////bar/", 149 "////foo8//bar///", 150 NULL, 151 }; 152 153 ucl_object_t *list = ucl_object_typed_new(UCL_ARRAY); 154 for (size_t i = 0; paths[i] != NULL; i++) { 155 ucl_array_append(list, ucl_object_fromstring_common(paths[i], 0, 0)); 156 } 157 158 ATF_REQUIRE(pkg_match_paths_list(list, "/target.so")); 159 ATF_REQUIRE(pkg_match_paths_list(list, "/foo1/whatever")); 160 ATF_REQUIRE(pkg_match_paths_list(list, "/foo2/thing.txt")); 161 ATF_REQUIRE(pkg_match_paths_list(list, "/foo3/bar/baz.so.1.1.1")); 162 ATF_REQUIRE(pkg_match_paths_list(list, "////foo4//bar/thingy")); 163 ATF_REQUIRE(pkg_match_paths_list(list, "/foo5//////bar/whatisit")); 164 ATF_REQUIRE(pkg_match_paths_list(list, "/foo6//bar/afile")); 165 ATF_REQUIRE(pkg_match_paths_list(list, "/foo7//////bar/foooo")); 166 ATF_REQUIRE(pkg_match_paths_list(list, "/foo8//bar///other")); 167 168 ATF_REQUIRE(!pkg_match_paths_list(list, "/notinpath/target.so")); 169 ATF_REQUIRE(!pkg_match_paths_list(list, "//////notinpath////other.so.1")); 170 ATF_REQUIRE(!pkg_match_paths_list(list, "/a/b/c/d/e/f/g")); 171 } 172 173 ATF_TP_ADD_TCS(tp) 174 { 175 ATF_TP_ADD_TC(tp, hidden_tempfile); 176 ATF_TP_ADD_TC(tp, random_suffix); 177 ATF_TP_ADD_TC(tp, json_escape); 178 ATF_TP_ADD_TC(tp, open_tempdir); 179 ATF_TP_ADD_TC(tp, get_http_auth); 180 ATF_TP_ADD_TC(tp, str_ends_with); 181 ATF_TP_ADD_TC(tp, match_paths); 182 183 return (atf_no_error()); 184 }