Mercurial > dropbear
comparison common-session.c @ 26:0969767bca0d
snapshot of stuff
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 26 Jul 2004 02:44:20 +0000 |
parents | 469950e86d0f |
children | f789045062e6 |
comparison
equal
deleted
inserted
replaced
25:e4b6e2d569b2 | 26:0969767bca0d |
---|---|
33 #include "random.h" | 33 #include "random.h" |
34 #include "kex.h" | 34 #include "kex.h" |
35 #include "channel.h" | 35 #include "channel.h" |
36 #include "atomicio.h" | 36 #include "atomicio.h" |
37 | 37 |
38 | |
38 struct sshsession ses; /* GLOBAL */ | 39 struct sshsession ses; /* GLOBAL */ |
39 | 40 |
40 /* need to know if the session struct has been initialised, this way isn't the | 41 /* need to know if the session struct has been initialised, this way isn't the |
41 * cleanest, but works OK */ | 42 * cleanest, but works OK */ |
42 int sessinitdone = 0; /* GLOBAL */ | 43 int sessinitdone = 0; /* GLOBAL */ |
43 | 44 |
44 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */ | 45 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */ |
45 int exitflag = 0; /* GLOBAL */ | 46 int exitflag = 0; /* GLOBAL */ |
46 | 47 |
48 void(*session_remoteclosed)() = NULL; | |
49 | |
50 | |
51 static void checktimeouts(); | |
47 static int ident_readln(int fd, char* buf, int count); | 52 static int ident_readln(int fd, char* buf, int count); |
48 | 53 |
49 | |
50 void(*session_remoteclosed)() = NULL; | |
51 | |
52 | |
53 /* called only at the start of a session, set up initial state */ | 54 /* called only at the start of a session, set up initial state */ |
54 void common_session_init(int sock) { | 55 void common_session_init(int sock, char* remotehost) { |
55 | 56 |
56 TRACE(("enter session_init")); | 57 TRACE(("enter session_init")); |
57 | 58 |
58 ses.remoteaddr = NULL; | 59 ses.remotehost = remotehost; |
59 ses.remotehost = NULL; | |
60 | 60 |
61 ses.sock = sock; | 61 ses.sock = sock; |
62 ses.maxfd = sock; | 62 ses.maxfd = sock; |
63 | 63 |
64 ses.connecttimeout = 0; | 64 ses.connecttimeout = 0; |
112 | 112 |
113 | 113 |
114 TRACE(("leave session_init")); | 114 TRACE(("leave session_init")); |
115 } | 115 } |
116 | 116 |
117 void session_loop(void(*loophandler)()) { | |
118 | |
119 fd_set readfd, writefd; | |
120 struct timeval timeout; | |
121 int val; | |
122 | |
123 /* main loop, select()s for all sockets in use */ | |
124 for(;;) { | |
125 | |
126 timeout.tv_sec = SELECT_TIMEOUT; | |
127 timeout.tv_usec = 0; | |
128 FD_ZERO(&writefd); | |
129 FD_ZERO(&readfd); | |
130 assert(ses.payload == NULL); | |
131 if (ses.sock != -1) { | |
132 FD_SET(ses.sock, &readfd); | |
133 if (!isempty(&ses.writequeue)) { | |
134 FD_SET(ses.sock, &writefd); | |
135 } | |
136 } | |
137 | |
138 /* set up for channels which require reading/writing */ | |
139 if (ses.dataallowed) { | |
140 setchannelfds(&readfd, &writefd); | |
141 } | |
142 val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout); | |
143 | |
144 if (exitflag) { | |
145 dropbear_exit("Terminated by signal"); | |
146 } | |
147 | |
148 if (val < 0) { | |
149 if (errno == EINTR) { | |
150 continue; | |
151 } else { | |
152 dropbear_exit("Error in select"); | |
153 } | |
154 } | |
155 | |
156 /* check for auth timeout, rekeying required etc */ | |
157 checktimeouts(); | |
158 | |
159 if (val == 0) { | |
160 /* timeout */ | |
161 TRACE(("select timeout")); | |
162 continue; | |
163 } | |
164 | |
165 /* process session socket's incoming/outgoing data */ | |
166 if (ses.sock != -1) { | |
167 if (FD_ISSET(ses.sock, &writefd) && !isempty(&ses.writequeue)) { | |
168 write_packet(); | |
169 } | |
170 | |
171 if (FD_ISSET(ses.sock, &readfd)) { | |
172 read_packet(); | |
173 } | |
174 | |
175 /* Process the decrypted packet. After this, the read buffer | |
176 * will be ready for a new packet */ | |
177 if (ses.payload != NULL) { | |
178 process_packet(); | |
179 } | |
180 } | |
181 | |
182 /* process pipes etc for the channels, ses.dataallowed == 0 | |
183 * during rekeying ) */ | |
184 if (ses.dataallowed) { | |
185 channelio(&readfd, &writefd); | |
186 } | |
187 | |
188 if (loophandler) { | |
189 loophandler(); | |
190 } | |
191 | |
192 } /* for(;;) */ | |
193 | |
194 /* Not reached */ | |
195 } | |
196 | |
117 /* clean up a session on exit */ | 197 /* clean up a session on exit */ |
118 void common_session_cleanup() { | 198 void common_session_cleanup() { |
119 | 199 |
120 TRACE(("enter session_cleanup")); | 200 TRACE(("enter session_cleanup")); |
121 | 201 |
132 chancleanup(); | 212 chancleanup(); |
133 | 213 |
134 TRACE(("leave session_cleanup")); | 214 TRACE(("leave session_cleanup")); |
135 } | 215 } |
136 | 216 |
137 /* Check all timeouts which are required. Currently these are the time for | 217 |
138 * user authentication, and the automatic rekeying. */ | |
139 void checktimeouts() { | |
140 | |
141 struct timeval tv; | |
142 long secs; | |
143 | |
144 if (gettimeofday(&tv, 0) < 0) { | |
145 dropbear_exit("Error getting time"); | |
146 } | |
147 | |
148 secs = tv.tv_sec; | |
149 | |
150 if (ses.connecttimeout != 0 && secs > ses.connecttimeout) { | |
151 dropbear_close("Timeout before auth"); | |
152 } | |
153 | |
154 /* we can't rekey if we haven't done remote ident exchange yet */ | |
155 if (ses.remoteident == NULL) { | |
156 return; | |
157 } | |
158 | |
159 if (!ses.kexstate.sentkexinit | |
160 && (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT | |
161 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){ | |
162 TRACE(("rekeying after timeout or max data reached")); | |
163 send_msg_kexinit(); | |
164 } | |
165 } | |
166 void session_identification() { | 218 void session_identification() { |
167 | 219 |
168 /* max length of 255 chars */ | 220 /* max length of 255 chars */ |
169 char linebuf[256]; | 221 char linebuf[256]; |
170 int len = 0; | 222 int len = 0; |
266 buf[pos] = '\0'; | 318 buf[pos] = '\0'; |
267 TRACE(("leave ident_readln: return %d", pos+1)); | 319 TRACE(("leave ident_readln: return %d", pos+1)); |
268 return pos+1; | 320 return pos+1; |
269 } | 321 } |
270 | 322 |
323 /* Check all timeouts which are required. Currently these are the time for | |
324 * user authentication, and the automatic rekeying. */ | |
325 static void checktimeouts() { | |
326 | |
327 struct timeval tv; | |
328 long secs; | |
329 | |
330 if (gettimeofday(&tv, 0) < 0) { | |
331 dropbear_exit("Error getting time"); | |
332 } | |
333 | |
334 secs = tv.tv_sec; | |
335 | |
336 if (ses.connecttimeout != 0 && secs > ses.connecttimeout) { | |
337 dropbear_close("Timeout before auth"); | |
338 } | |
339 | |
340 /* we can't rekey if we haven't done remote ident exchange yet */ | |
341 if (ses.remoteident == NULL) { | |
342 return; | |
343 } | |
344 | |
345 if (!ses.kexstate.sentkexinit | |
346 && (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT | |
347 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){ | |
348 TRACE(("rekeying after timeout or max data reached")); | |
349 send_msg_kexinit(); | |
350 } | |
351 } | |
352 |