comparison svr-agentfwd.c @ 11:f76c9389e9e0

Mostly done with the listener changeover
author Matt Johnston <matt@ucc.asn.au>
date Thu, 03 Jun 2004 17:22:48 +0000
parents bc6477a6c393
children db2c8e6fb284
comparison
equal deleted inserted replaced
9:7f77962de998 11:f76c9389e9e0
36 #include "chansession.h" 36 #include "chansession.h"
37 #include "channel.h" 37 #include "channel.h"
38 #include "packet.h" 38 #include "packet.h"
39 #include "buffer.h" 39 #include "buffer.h"
40 #include "random.h" 40 #include "random.h"
41 #include "listener.h"
41 42
42 #define AGENTDIRPREFIX "/tmp/dropbear-" 43 #define AGENTDIRPREFIX "/tmp/dropbear-"
43 44
44 static int send_msg_channel_open_agent(int fd); 45 static int send_msg_channel_open_agent(int fd);
45 static int bindagent(struct ChanSess * chansess); 46 static int bindagent(int fd, struct ChanSess * chansess);
47 static void agentaccept(struct Listener * listener);
46 48
47 /* Handles client requests to start agent forwarding, sets up listening socket. 49 /* Handles client requests to start agent forwarding, sets up listening socket.
48 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ 50 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
49 int agentreq(struct ChanSess * chansess) { 51 int agentreq(struct ChanSess * chansess) {
50 52
51 if (chansess->agentfd != -1) { 53 int fd;
54
55 if (chansess->agentlistener != NULL) {
52 return DROPBEAR_FAILURE; 56 return DROPBEAR_FAILURE;
53 } 57 }
54 58
55 /* create listening socket */ 59 /* create listening socket */
56 chansess->agentfd = socket(PF_UNIX, SOCK_STREAM, 0); 60 fd = socket(PF_UNIX, SOCK_STREAM, 0);
57 if (chansess->agentfd < 0) { 61 if (fd < 0) {
58 goto fail; 62 goto fail;
59 } 63 }
60 64
61 /* create the unix socket dir and file */ 65 /* create the unix socket dir and file */
62 if (bindagent(chansess) == DROPBEAR_FAILURE) { 66 if (bindagent(fd, chansess) == DROPBEAR_FAILURE) {
63 return DROPBEAR_FAILURE; 67 return DROPBEAR_FAILURE;
64 } 68 }
65 69
66 /* listen */ 70 /* listen */
67 if (listen(chansess->agentfd, 20) < 0) { 71 if (listen(fd, 20) < 0) {
68 goto fail; 72 goto fail;
69 } 73 }
70 74
71 /* set non-blocking */ 75 /* set non-blocking */
72 if (fcntl(chansess->agentfd, F_SETFL, O_NONBLOCK) < 0) { 76 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
73 goto fail; 77 goto fail;
74 } 78 }
75 79
76 /* channel.c's channel fd code will handle the socket now */ 80 /* pass if off to listener */
77 81 chansess->agentlistener = new_listener( fd, 0, chansess,
78 /* set the maxfd so that select() loop will notice it */ 82 agentaccept, NULL);
79 ses.maxfd = MAX(ses.maxfd, chansess->agentfd); 83
84 if (chansess->agentlistener == NULL) {
85 goto fail;
86 }
80 87
81 return DROPBEAR_SUCCESS; 88 return DROPBEAR_SUCCESS;
82 89
83 fail: 90 fail:
84 /* cleanup */ 91 /* cleanup */
88 } 95 }
89 96
90 /* accepts a connection on the forwarded socket and opens a new channel for it 97 /* accepts a connection on the forwarded socket and opens a new channel for it
91 * back to the client */ 98 * back to the client */
92 /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ 99 /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
93 int agentaccept(struct ChanSess * chansess) { 100 static void agentaccept(struct Listener * listener) {
94 101
95 int fd; 102 int fd;
96 103
97 fd = accept(chansess->agentfd, NULL, NULL); 104 fd = accept(listener->sock, NULL, NULL);
98 if (fd < 0) { 105 if (fd < 0) {
99 return DROPBEAR_FAILURE; 106 return;
100 } 107 }
101 108
102 return send_msg_channel_open_agent(fd); 109 if (send_msg_channel_open_agent(listener->sock) != DROPBEAR_SUCCESS) {
110 close(fd);
111 }
103 112
104 } 113 }
105 114
106 /* set up the environment variable pointing to the socket. This is called 115 /* set up the environment variable pointing to the socket. This is called
107 * just before command/shell execution, after dropping priveleges */ 116 * just before command/shell execution, after dropping priveleges */
108 void agentset(struct ChanSess * chansess) { 117 void agentset(struct ChanSess * chansess) {
109 118
110 char *path = NULL; 119 char *path = NULL;
111 int len; 120 int len;
112 121
113 if (chansess->agentfd == -1) { 122 if (chansess->agentlistener == NULL) {
114 return; 123 return;
115 } 124 }
116 125
117 /* 2 for "/" and "\0" */ 126 /* 2 for "/" and "\0" */
118 len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2; 127 len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2;
129 char *path = NULL; 138 char *path = NULL;
130 uid_t uid; 139 uid_t uid;
131 gid_t gid; 140 gid_t gid;
132 int len; 141 int len;
133 142
134 if (chansess->agentfd == -1) { 143 if (chansess->agentlistener != NULL) {
135 return; 144 remove_listener(chansess->agentlistener);
136 } 145 chansess->agentlistener = NULL;
137 146 }
138 close(chansess->agentfd); 147
139 148 if (chansess->agentfile && chansess->agentdir) {
140 /* Remove the dir as the user. That way they can't cause problems except 149
141 * for themselves */ 150 /* Remove the dir as the user. That way they can't cause problems except
142 uid = getuid(); 151 * for themselves */
143 gid = getgid(); 152 uid = getuid();
144 if ((setegid(svr_ses.authstate.pw->pw_gid)) < 0 || 153 gid = getgid();
145 (seteuid(svr_ses.authstate.pw->pw_uid)) < 0) { 154 if ((setegid(svr_ses.authstate.pw->pw_gid)) < 0 ||
146 dropbear_exit("failed to set euid"); 155 (seteuid(svr_ses.authstate.pw->pw_uid)) < 0) {
147 } 156 dropbear_exit("failed to set euid");
148 157 }
149 /* 2 for "/" and "\0" */ 158
150 len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2; 159 /* 2 for "/" and "\0" */
151 160 len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2;
152 path = m_malloc(len); 161
153 snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile); 162 path = m_malloc(len);
154 unlink(path); 163 snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile);
155 m_free(path); 164 unlink(path);
156 165 m_free(path);
157 rmdir(chansess->agentdir); 166
158 167 rmdir(chansess->agentdir);
159 if ((seteuid(uid)) < 0 || 168
160 (setegid(gid)) < 0) { 169 if ((seteuid(uid)) < 0 ||
161 dropbear_exit("failed to revert euid"); 170 (setegid(gid)) < 0) {
162 } 171 dropbear_exit("failed to revert euid");
163 172 }
164 m_free(chansess->agentfile); 173
165 m_free(chansess->agentdir); 174 m_free(chansess->agentfile);
166 175 m_free(chansess->agentdir);
167 } 176 }
177
178 }
179
180 static const struct ChanType chan_agent = {
181 0, /* sepfds */
182 "[email protected]",
183 NULL,
184 NULL,
185 NULL,
186 NULL
187 };
188
168 189
169 /* helper for accepting an agent request */ 190 /* helper for accepting an agent request */
170 static int send_msg_channel_open_agent(int fd) { 191 static int send_msg_channel_open_agent(int fd) {
171 192
172 if (send_msg_channel_open_init(fd, CHANNEL_ID_AGENT, 193 if (send_msg_channel_open_init(fd, &chan_agent) == DROPBEAR_SUCCESS) {
173 "[email protected]") == DROPBEAR_SUCCESS) {
174 encrypt_packet(); 194 encrypt_packet();
175 return DROPBEAR_SUCCESS; 195 return DROPBEAR_SUCCESS;
176 } else { 196 } else {
177 return DROPBEAR_FAILURE; 197 return DROPBEAR_FAILURE;
178 } 198 }
179 } 199 }
180 200
181 /* helper for creating the agent socket-file 201 /* helper for creating the agent socket-file
182 returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ 202 returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
183 static int bindagent(struct ChanSess * chansess) { 203 static int bindagent(int fd, struct ChanSess * chansess) {
184 204
185 struct sockaddr_un addr; 205 struct sockaddr_un addr;
186 unsigned int prefix; 206 unsigned int prefix;
187 char path[sizeof(addr.sun_path)], sockfile[sizeof(addr.sun_path)]; 207 char path[sizeof(addr.sun_path)], sockfile[sizeof(addr.sun_path)];
188 mode_t mode; 208 mode_t mode;
223 /* Format is "/tmp/dropbear-0246dead/auth-d00f7654-23". 243 /* Format is "/tmp/dropbear-0246dead/auth-d00f7654-23".
224 * The "23" is the file desc, the random data is to avoid collisions 244 * The "23" is the file desc, the random data is to avoid collisions
225 * between subsequent user processes reusing socket fds (odds are now 245 * between subsequent user processes reusing socket fds (odds are now
226 * 1/(2^64) */ 246 * 1/(2^64) */
227 genrandom((unsigned char*)&prefix, sizeof(prefix)); 247 genrandom((unsigned char*)&prefix, sizeof(prefix));
228 snprintf(sockfile, sizeof(sockfile), "auth-%.8x-%d", prefix, 248 snprintf(sockfile, sizeof(sockfile), "auth-%.8x-%d", prefix, fd);
229 chansess->agentfd); 249
230 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile); 250 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile);
231 251
232 if (bind(chansess->agentfd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { 252 if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
233 chansess->agentdir = strdup(path); 253 chansess->agentdir = m_strdup(path);
234 chansess->agentfile = strdup(sockfile); 254 chansess->agentfile = m_strdup(sockfile);
235 ret = DROPBEAR_SUCCESS; 255 ret = DROPBEAR_SUCCESS;
236 } 256 }
237 257
238 258
239 out: 259 out: