1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2004 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20/* 21 * Test Name: bind02 22 * 23 * Test Description: 24 * Make sure bind() gives EACCESS error for (non-root) users. 25 * 26 * Usage: <for command-line> 27 * bind01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 28 * where, -c n : Run n copies concurrently. 29 * -e : Turn on errno logging. 30 * -i n : Execute test n times. 31 * -I x : Execute test for x seconds. 32 * -P x : Pause for x seconds between iterations. 33 * -t : Turn on syscall timing. 34 * 35 * HISTORY 36 * 07/2004 Written by Dan Jones 37 * 07/2004 Ported to LTP format by Robbie Williamson 38 * 39 * RESTRICTIONS: 40 * None. 41 * 42 */ 43 44#include <stdio.h> 45#include <stdlib.h> 46#include <unistd.h> 47#include <errno.h> 48#include <fcntl.h> 49#include <pwd.h> 50#include <grp.h> 51 52#include <sys/types.h> 53#include <sys/socket.h> 54#include <sys/un.h> 55 56#include <netinet/in.h> 57 58#include "test.h" 59 60char *TCID = "bind02"; 61int testno; 62int TST_TOTAL = 1; 63 64/* This port needs to be a Privledged port */ 65#define TCP_PRIVLEGED_COM_PORT 463 66 67struct passwd *pw; 68struct group *gr; 69 70uid_t uid; 71gid_t gid; 72 73int rc; 74 75void try_bind(void) 76{ 77 struct sockaddr_in servaddr; 78 int sockfd, r_value; 79 80 // Set effective user/group 81 if ((rc = setegid(gid)) == -1) { 82 tst_brkm(TBROK | TERRNO, 0, "setegid(%u) failed", gid); 83 } 84 if ((rc = seteuid(uid)) == -1) { 85 tst_brkm(TBROK | TERRNO, 0, "seteuid(%u) failed", uid); 86 } 87 88 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 89 tst_brkm(TBROK | TERRNO, 0, "socket() failed"); 90 } 91 92 memset(&servaddr, 0, sizeof(servaddr)); 93 servaddr.sin_family = AF_INET; 94 servaddr.sin_port = htons(TCP_PRIVLEGED_COM_PORT); 95 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 96 r_value = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 97 if (r_value) { 98 if (errno == EACCES) { 99 tst_resm(TPASS, "correct error"); 100 } else { 101 tst_resm(TFAIL, "incorrect error, %d", r_value); 102 } 103 } else { 104 tst_resm(TFAIL, "user was able to bind successfully"); 105 } 106 107 close(sockfd); 108 109 // Set effective user/group 110 if ((rc = setegid(0)) == -1) { 111 tst_brkm(TBROK | TERRNO, 0, "setegid(0) reset failed"); 112 } 113 if ((rc = seteuid(uid)) == -1) { 114 /* XXX: is this seteuid() correct !? it isnt a reset if we 115 * made the same exact call above ... 116 */ 117 tst_brkm(TBROK | TERRNO, 0, "seteuid(%u) reset failed", uid); 118 } 119 120} 121 122int main(int argc, char *argv[]) 123{ 124 char *username = "nobody"; 125 126 tst_parse_opts(argc, argv, NULL, NULL); 127 128 tst_require_root(); 129 130 if ((pw = getpwnam(username)) == NULL) { 131 tst_brkm(TBROK, 0, "Username - %s - not found", username); 132 } 133 134 if ((gr = getgrgid(pw->pw_gid)) == NULL) { 135 tst_brkm(TBROK | TERRNO, 0, "getgrgid(%u) failed", pw->pw_gid); 136 } 137 138 uid = pw->pw_uid; 139 gid = gr->gr_gid; 140 141 tst_resm(TINFO, "Socket will try to be bind by user: %s, group: %s", 142 pw->pw_name, gr->gr_name); 143 144 try_bind(); 145 tst_exit(); 146} 147