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