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 char nobody_uid[] = "nobody";
73
74 int rc;
75
try_bind(void)76 void try_bind(void)
77 {
78 struct sockaddr_in servaddr;
79 int sockfd, r_value;
80
81 // Set effective user/group
82 if ((rc = setegid(gid)) == -1) {
83 tst_brkm(TBROK | TERRNO, 0, "setegid(%u) failed", gid);
84 }
85 if ((rc = seteuid(uid)) == -1) {
86 tst_brkm(TBROK | TERRNO, 0, "seteuid(%u) failed", uid);
87 }
88
89 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
90 tst_brkm(TBROK | TERRNO, 0, "socket() failed");
91 }
92
93 memset(&servaddr, 0, sizeof(servaddr));
94 servaddr.sin_family = AF_INET;
95 servaddr.sin_port = htons(TCP_PRIVLEGED_COM_PORT);
96 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
97 r_value = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
98 if (r_value) {
99 if (errno == EACCES) {
100 tst_resm(TPASS, "correct error");
101 } else {
102 tst_resm(TFAIL, "incorrect error, %d", r_value);
103 }
104 } else {
105 tst_resm(TFAIL, "user was able to bind successfully");
106 }
107
108 close(sockfd);
109
110 // Set effective user/group
111 if ((rc = setegid(0)) == -1) {
112 tst_brkm(TBROK | TERRNO, 0, "setegid(0) reset failed");
113 }
114 if ((rc = seteuid(uid)) == -1) {
115 /* XXX: is this seteuid() correct !? it isnt a reset if we
116 * made the same exact call above ...
117 */
118 tst_brkm(TBROK | TERRNO, 0, "seteuid(%u) reset failed", uid);
119 }
120
121 }
122
main(int argc,char * argv[])123 int main(int argc, char *argv[])
124 {
125
126 /* FreeBSD has set limits for user login name -- MAXLOGNAME, but
127 * Linux doesn't have that limitation apparently. */
128 char *username = NULL;
129
130 tst_require_root();
131
132 if (argc != 2) {
133 tst_resm(TINFO, "Defaulting to user nobody");
134 username = strdup(nobody_uid);
135 } else {
136 /* Get test user uid/gid. */
137 username = argv[1];
138 }
139
140 if ((pw = getpwnam(username)) == NULL) {
141 tst_brkm(TBROK, 0, "Username - %s - not found", username);
142 }
143
144 if ((gr = getgrgid(pw->pw_gid)) == NULL) {
145 tst_brkm(TBROK | TERRNO, 0, "getgrgid(%u) failed", pw->pw_gid);
146 }
147
148 uid = pw->pw_uid;
149 gid = gr->gr_gid;
150
151 tst_resm(TINFO, "Socket will try to be bind by user: %s, group: %s",
152 pw->pw_name, gr->gr_name);
153
154 try_bind();
155 tst_exit();
156 }
157