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"
43 static void svr_remoteclosed();
45 struct serversession svr_ses
; /* GLOBAL */
47 static const packettype svr_packettypes
[] = {
48 {SSH_MSG_CHANNEL_DATA
, recv_msg_channel_data
},
49 {SSH_MSG_CHANNEL_WINDOW_ADJUST
, recv_msg_channel_window_adjust
},
50 {SSH_MSG_USERAUTH_REQUEST
, recv_msg_userauth_request
}, /* server */
51 {SSH_MSG_SERVICE_REQUEST
, recv_msg_service_request
}, /* server */
52 {SSH_MSG_KEXINIT
, recv_msg_kexinit
},
53 {SSH_MSG_KEXDH_INIT
, recv_msg_kexdh_init
}, /* server */
54 {SSH_MSG_NEWKEYS
, recv_msg_newkeys
},
55 {SSH_MSG_GLOBAL_REQUEST
, recv_msg_global_request_remotetcp
},
56 {SSH_MSG_CHANNEL_REQUEST
, recv_msg_channel_request
},
57 {SSH_MSG_CHANNEL_OPEN
, recv_msg_channel_open
},
58 {SSH_MSG_CHANNEL_EOF
, recv_msg_channel_eof
},
59 {SSH_MSG_CHANNEL_CLOSE
, recv_msg_channel_close
},
60 #ifdef USING_LISTENERS
61 {SSH_MSG_CHANNEL_OPEN_CONFIRMATION
, recv_msg_channel_open_confirmation
},
62 {SSH_MSG_CHANNEL_OPEN_FAILURE
, recv_msg_channel_open_failure
},
67 static const struct ChanType
*svr_chantypes
[] = {
69 #ifdef ENABLE_SVR_LOCALTCPFWD
72 NULL
/* Null termination is mandatory. */
76 svr_session_cleanup(void)
78 /* free potential public key options */
79 svr_pubkey_options_cleanup();
82 void svr_session(int sock
, int childpipe
) {
87 common_session_init(sock
, sock
);
89 /* Initialise server specific parts of the session */
90 svr_ses
.childpipe
= childpipe
;
92 svr_ses
.server_pid
= getpid();
95 chaninitialise(svr_chantypes
);
96 svr_chansessinitialise();
98 ses
.connect_time
= time(NULL
);
100 /* for logging the remote address */
101 get_socket_address(ses
.sock_in
, NULL
, NULL
, &host
, &port
, 0);
102 len
= strlen(host
) + strlen(port
) + 2;
103 svr_ses
.addrstring
= m_malloc(len
);
104 snprintf(svr_ses
.addrstring
, len
, "%s:%s", host
, port
);
108 get_socket_address(ses
.sock_in
, NULL
, NULL
,
109 &svr_ses
.remotehost
, NULL
, 1);
111 /* set up messages etc */
112 ses
.remoteclosed
= svr_remoteclosed
;
113 ses
.extra_session_cleanup
= svr_session_cleanup
;
115 /* packet handlers */
116 ses
.packettypes
= svr_packettypes
;
120 /* We're ready to go now */
123 /* exchange identification, version etc */
124 send_session_identification();
126 /* start off with key exchange */
129 /* Run the main for loop. NULL is for the dispatcher - only the client
130 * code makes use of it */
137 /* failure exit - format must be <= 100 chars */
138 void svr_dropbear_exit(int exitcode
, const char* format
, va_list param
) {
143 /* before session init */
144 snprintf(fmtbuf
, sizeof(fmtbuf
),
145 "Premature exit: %s", format
);
146 } else if (ses
.authstate
.authdone
) {
147 /* user has authenticated */
148 snprintf(fmtbuf
, sizeof(fmtbuf
),
150 ses
.authstate
.pw_name
, format
);
151 } else if (ses
.authstate
.pw_name
) {
152 /* we have a potential user */
153 snprintf(fmtbuf
, sizeof(fmtbuf
),
154 "Exit before auth (user '%s', %d fails): %s",
155 ses
.authstate
.pw_name
, ses
.authstate
.failcount
, format
);
157 /* before userauth */
158 snprintf(fmtbuf
, sizeof(fmtbuf
),
159 "Exit before auth: %s", format
);
162 _dropbear_log(LOG_INFO
, fmtbuf
, param
);
165 /* For uclinux only the main server process should cleanup - we don't want
166 * forked children doing that */
167 if (svr_ses
.server_pid
== getpid())
170 /* must be after we've done with username etc */
178 /* priority is priority as with syslog() */
179 void svr_dropbear_log(int priority
, const char* format
, va_list param
) {
186 vsnprintf(printbuf
, sizeof(printbuf
), format
, param
);
188 #ifndef DISABLE_SYSLOG
189 if (svr_opts
.usingsyslog
) {
190 syslog(priority
, "%s", printbuf
);
194 /* if we are using DEBUG_TRACE, we want to print to stderr even if
195 * syslog is used, so it is included in error reports */
197 havetrace
= debug_trace
;
200 if (!svr_opts
.usingsyslog
|| havetrace
)
202 struct tm
* local_tm
= NULL
;
203 timesec
= time(NULL
);
204 local_tm
= localtime(×ec
);
206 || strftime(datestr
, sizeof(datestr
), "%b %d %H:%M:%S",
209 /* upon failure, just print the epoch-seconds time. */
210 snprintf(datestr
, sizeof(datestr
), "%d", (int)timesec
);
212 fprintf(stderr
, "[%d] %s %s\n", getpid(), datestr
, printbuf
);
216 /* called when the remote side closes the connection */
217 static void svr_remoteclosed() {
219 m_close(ses
.sock_in
);
220 m_close(ses
.sock_out
);
223 dropbear_close("Exited normally");