1 /* $OpenBSD: t_getlogin.c,v 1.2 2021/12/13 16:56:48 deraadt Exp $ */ 2 /* $NetBSD: t_getlogin.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */ 3 4 /*- 5 * Copyright (c) 2011 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jukka Ruohonen. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "macros.h" 34 35 #include <sys/wait.h> 36 37 #include "atf-c.h" 38 #include <errno.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <limits.h> 42 #include <unistd.h> 43 44 ATF_TC(getlogin_r_err); 45 ATF_TC_HEAD(getlogin_r_err, tc) 46 { 47 atf_tc_set_md_var(tc, "descr", "Test errors from getlogin_r(2)"); 48 } 49 50 ATF_TC_BODY(getlogin_r_err, tc) 51 { 52 char small[0]; 53 54 ATF_REQUIRE(getlogin_r(small, sizeof(small)) == ERANGE); 55 } 56 57 ATF_TC(getlogin_same); 58 ATF_TC_HEAD(getlogin_same, tc) 59 { 60 atf_tc_set_md_var(tc, "descr", "getlogin(2) vs. getlogin_r(2)"); 61 } 62 63 ATF_TC_BODY(getlogin_same, tc) 64 { 65 char buf[LOGIN_NAME_MAX]; 66 char *str; 67 68 str = getlogin(); 69 70 if (str == NULL) 71 return; 72 73 ATF_REQUIRE(getlogin_r(buf, sizeof(buf)) == 0); 74 75 if (strcmp(str, buf) != 0) 76 atf_tc_fail("getlogin(2) and getlogin_r(2) differ"); 77 } 78 79 ATF_TC(setlogin_basic); 80 ATF_TC_HEAD(setlogin_basic, tc) 81 { 82 atf_tc_set_md_var(tc, "descr", "Test that setlogin(2) works"); 83 atf_tc_set_md_var(tc, "require.user", "root"); 84 } 85 86 ATF_TC_BODY(setlogin_basic, tc) 87 { 88 char *name; 89 pid_t pid; 90 int sta; 91 92 pid = fork(); 93 ATF_REQUIRE(pid >= 0); 94 95 if (pid == 0) { 96 97 (void)setsid(); 98 99 if (setlogin("foobar") != 0) 100 _exit(EXIT_FAILURE); 101 102 name = getlogin(); 103 104 if (name == NULL) 105 _exit(EXIT_FAILURE); 106 107 if (strcmp(name, "foobar") != 0) 108 _exit(EXIT_FAILURE); 109 110 _exit(EXIT_SUCCESS); 111 } 112 113 (void)wait(&sta); 114 115 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 116 atf_tc_fail("setlogin(2) failed to set login name"); 117 } 118 119 ATF_TC(setlogin_err); 120 ATF_TC_HEAD(setlogin_err, tc) 121 { 122 atf_tc_set_md_var(tc, "descr", "Test errors from setlogin(2)"); 123 atf_tc_set_md_var(tc, "require.user", "root"); 124 } 125 126 ATF_TC_BODY(setlogin_err, tc) 127 { 128 char buf[LOGIN_NAME_MAX + 1]; 129 char *name; 130 pid_t pid; 131 int sta; 132 133 pid = fork(); 134 ATF_REQUIRE(pid >= 0); 135 136 (void)memset(buf, 'x', sizeof(buf)); 137 138 if (pid == 0) { 139 140 (void)setsid(); 141 142 errno = 0; 143 144 if (setlogin(buf) != -1) 145 _exit(EINVAL); 146 147 if (errno != EINVAL) 148 _exit(EINVAL); 149 150 errno = 0; 151 152 if (setlogin((void *)-1) != -1) 153 _exit(EFAULT); 154 155 if (errno != EFAULT) 156 _exit(EFAULT); 157 158 name = getlogin(); 159 160 if (name == NULL) 161 _exit(EXIT_FAILURE); 162 163 if (strcmp(name, "foobar") == 0) 164 _exit(EXIT_FAILURE); 165 166 _exit(EXIT_SUCCESS); 167 } 168 169 (void)wait(&sta); 170 171 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) { 172 173 if (WEXITSTATUS(sta) == EFAULT) 174 atf_tc_fail("expected EFAULT, but the call succeeded"); 175 176 if (WEXITSTATUS(sta) == EINVAL) 177 atf_tc_fail("expected EINVAL, but the call succeeded"); 178 179 atf_tc_fail("setlogin(2) failed, but login name was set"); 180 } 181 } 182 183 ATF_TC(setlogin_perm); 184 ATF_TC_HEAD(setlogin_perm, tc) 185 { 186 atf_tc_set_md_var(tc, "descr", "Test setlogin(2) as normal user"); 187 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 188 } 189 190 ATF_TC_BODY(setlogin_perm, tc) 191 { 192 char *name; 193 pid_t pid; 194 int sta; 195 196 pid = fork(); 197 ATF_REQUIRE(pid >= 0); 198 199 if (pid == 0) { 200 201 (void)setsid(); 202 203 errno = 0; 204 205 if (setlogin("foobar") != -1) 206 _exit(EXIT_FAILURE); 207 208 if (errno != EPERM) 209 _exit(EXIT_FAILURE); 210 211 name = getlogin(); 212 213 if (name == NULL) 214 _exit(EXIT_FAILURE); 215 216 if (strcmp(name, "foobar") == 0) 217 _exit(EXIT_FAILURE); 218 219 _exit(EXIT_SUCCESS); 220 } 221 222 (void)wait(&sta); 223 224 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 225 atf_tc_fail("login name was set as an unprivileged user"); 226 } 227 228 ATF_TP_ADD_TCS(tp) 229 { 230 231 ATF_TP_ADD_TC(tp, getlogin_r_err); 232 ATF_TP_ADD_TC(tp, getlogin_same); 233 ATF_TP_ADD_TC(tp, setlogin_basic); 234 ATF_TP_ADD_TC(tp, setlogin_err); 235 ATF_TP_ADD_TC(tp, setlogin_perm); 236 237 return atf_no_error(); 238 } 239