Mercurial > dropbear
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: |