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
60 char *TCID = "bind02";
61 int testno;
62 int TST_TOTAL = 1;
63
64 /* This port needs to be a Privledged port */
65 #define TCP_PRIVLEGED_COM_PORT 463
66
67 struct passwd *pw;
68 struct group *gr;
69
70 uid_t uid;
71 gid_t gid;
72
73 int rc;
74
try_bind(void)75 void 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
main(int argc,char * argv[])122 int 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