2 * Dropbear - a SSH2 server
4 * Copyright (c) 2002,2003 Matt Johnston
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 #include "chansession.h"
42 #include "crypto_desc.h"
44 static void svr_remoteclosed();
46 struct serversession svr_ses
; /* GLOBAL */
48 static const packettype svr_packettypes
[] = {
49 {SSH_MSG_CHANNEL_DATA
, recv_msg_channel_data
},
50 {SSH_MSG_CHANNEL_WINDOW_ADJUST
, recv_msg_channel_window_adjust
},
51 {SSH_MSG_USERAUTH_REQUEST
, recv_msg_userauth_request
}, /* server */
52 {SSH_MSG_SERVICE_REQUEST
, recv_msg_service_request
}, /* server */
53 {SSH_MSG_KEXINIT
, recv_msg_kexinit
},
54 {SSH_MSG_KEXDH_INIT
, recv_msg_kexdh_init
}, /* server */
55 {SSH_MSG_NEWKEYS
, recv_msg_newkeys
},
56 {SSH_MSG_GLOBAL_REQUEST
, recv_msg_global_request_remotetcp
},
57 {SSH_MSG_CHANNEL_REQUEST
, recv_msg_channel_request
},
58 {SSH_MSG_CHANNEL_OPEN
, recv_msg_channel_open
},
59 {SSH_MSG_CHANNEL_EOF
, recv_msg_channel_eof
},
60 {SSH_MSG_CHANNEL_CLOSE
, recv_msg_channel_close
},
61 {SSH_MSG_CHANNEL_SUCCESS
, ignore_recv_response
},
62 {SSH_MSG_CHANNEL_FAILURE
, ignore_recv_response
},
63 {SSH_MSG_REQUEST_FAILURE
, ignore_recv_response
}, /* for keepalive */
64 {SSH_MSG_REQUEST_SUCCESS
, ignore_recv_response
}, /* client */
65 #ifdef USING_LISTENERS
66 {SSH_MSG_CHANNEL_OPEN_CONFIRMATION
, recv_msg_channel_open_confirmation
},
67 {SSH_MSG_CHANNEL_OPEN_FAILURE
, recv_msg_channel_open_failure
},
72 static const struct ChanType
*svr_chantypes
[] = {
74 #ifdef ENABLE_SVR_LOCALTCPFWD
77 NULL
/* Null termination is mandatory. */
81 svr_session_cleanup(void)
83 /* free potential public key options */
84 svr_pubkey_options_cleanup();
89 if (svr_ses
.connect_time
!= 0
90 && monotonic_now() - svr_ses
.connect_time
>= AUTH_TIMEOUT
) {
91 dropbear_close("Timeout before auth");
95 void svr_session(int sock
, int childpipe
) {
99 common_session_init(sock
, sock
);
101 svr_ses
.connect_time
= monotonic_now();;
103 /* Initialise server specific parts of the session */
104 svr_ses
.childpipe
= childpipe
;
106 svr_ses
.server_pid
= getpid();
108 svr_authinitialise();
109 chaninitialise(svr_chantypes
);
110 svr_chansessinitialise();
112 /* for logging the remote address */
113 get_socket_address(ses
.sock_in
, NULL
, NULL
, &host
, &port
, 0);
114 len
= strlen(host
) + strlen(port
) + 2;
115 svr_ses
.addrstring
= m_malloc(len
);
116 snprintf(svr_ses
.addrstring
, len
, "%s:%s", host
, port
);
120 get_socket_address(ses
.sock_in
, NULL
, NULL
,
121 &svr_ses
.remotehost
, NULL
, 1);
123 /* set up messages etc */
124 ses
.remoteclosed
= svr_remoteclosed
;
125 ses
.extra_session_cleanup
= svr_session_cleanup
;
127 /* packet handlers */
128 ses
.packettypes
= svr_packettypes
;
132 /* We're ready to go now */
135 /* exchange identification, version etc */
136 send_session_identification();
138 /* start off with key exchange */
141 /* Run the main for loop. NULL is for the dispatcher - only the client
142 * code makes use of it */
143 session_loop(svr_sessionloop
);
149 /* failure exit - format must be <= 100 chars */
150 void svr_dropbear_exit(int exitcode
, const char* format
, va_list param
) {
155 /* before session init */
156 snprintf(fmtbuf
, sizeof(fmtbuf
),
157 "Early exit: %s", format
);
158 } else if (ses
.authstate
.authdone
) {
159 /* user has authenticated */
160 snprintf(fmtbuf
, sizeof(fmtbuf
),
162 ses
.authstate
.pw_name
, format
);
163 } else if (ses
.authstate
.pw_name
) {
164 /* we have a potential user */
165 snprintf(fmtbuf
, sizeof(fmtbuf
),
166 "Exit before auth (user '%s', %d fails): %s",
167 ses
.authstate
.pw_name
, ses
.authstate
.failcount
, format
);
169 /* before userauth */
170 snprintf(fmtbuf
, sizeof(fmtbuf
),
171 "Exit before auth: %s", format
);
174 _dropbear_log(LOG_INFO
, fmtbuf
, param
);
177 /* For uclinux only the main server process should cleanup - we don't want
178 * forked children doing that */
179 if (svr_ses
.server_pid
== getpid())
182 /* must be after we've done with username etc */
190 /* priority is priority as with syslog() */
191 void svr_dropbear_log(int priority
, const char* format
, va_list param
) {
198 vsnprintf(printbuf
, sizeof(printbuf
), format
, param
);
200 #ifndef DISABLE_SYSLOG
201 if (svr_opts
.usingsyslog
) {
202 syslog(priority
, "%s", printbuf
);
206 /* if we are using DEBUG_TRACE, we want to print to stderr even if
207 * syslog is used, so it is included in error reports */
209 havetrace
= debug_trace
;
212 if (!svr_opts
.usingsyslog
|| havetrace
)
214 struct tm
* local_tm
= NULL
;
215 timesec
= time(NULL
);
216 local_tm
= localtime(×ec
);
218 || strftime(datestr
, sizeof(datestr
), "%b %d %H:%M:%S",
221 /* upon failure, just print the epoch-seconds time. */
222 snprintf(datestr
, sizeof(datestr
), "%d", (int)timesec
);
224 fprintf(stderr
, "[%d] %s %s\n", getpid(), datestr
, printbuf
);
228 /* called when the remote side closes the connection */
229 static void svr_remoteclosed() {
231 m_close(ses
.sock_in
);
232 m_close(ses
.sock_out
);
235 dropbear_close("Exited normally");