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
32 svr_runopts svr_opts
; /* GLOBAL */
34 static void printhelp(const char * progname
);
35 static void addportandaddress(char* spec
);
37 static void printhelp(const char * progname
) {
39 fprintf(stderr
, "Dropbear sshd v%s\n"
40 "Usage: %s [options]\n"
42 "-b bannerfile Display the contents of bannerfile"
43 " before user login\n"
46 "-d dsskeyfile Use dsskeyfile for the DSS host key\n"
50 "-r rsakeyfile Use rsakeyfile for the RSA host key\n"
53 "-F Don't fork into background\n"
55 "(Syslog support not compiled in, using stderr)\n"
57 "-E Log to stderr rather than syslog\n"
60 "-m Don't display the motd on login\n"
62 "-w Disallow root logins\n"
63 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
64 "-s Disable password logins\n"
65 "-g Disable password logins for root\n"
67 #ifdef ENABLE_SVR_LOCALTCPFWD
68 "-j Disable local port forwarding\n"
70 #ifdef ENABLE_SVR_REMOTETCPFWD
71 "-k Disable remote port forwarding\n"
72 "-a Allow connections to forwarded ports from any host\n"
75 " Listen on specified tcp port (and optionally address),\n"
76 " up to %d can be specified\n"
77 " (default port is %s if none specified)\n"
78 "-P PidFile Create pid file PidFile\n"
81 "-i Start for inetd\n"
83 "-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
84 "-K <keepalive> (0 is never, default %d, in seconds)\n"
85 "-I <idle_timeout> (0 is never, default %d, in seconds)\n"
87 "-v verbose (compiled with DEBUG_TRACE)\n"
89 ,DROPBEAR_VERSION
, progname
,
96 DROPBEAR_MAX_PORTS
, DROPBEAR_DEFPORT
, DROPBEAR_PIDFILE
,
97 DEFAULT_RECV_WINDOW
, DEFAULT_KEEPALIVE
, DEFAULT_IDLE_TIMEOUT
);
100 void svr_getopts(int argc
, char ** argv
) {
105 char* recv_window_arg
= NULL
;
106 char* keepalive_arg
= NULL
;
107 char* idle_timeout_arg
= NULL
;
109 /* see printhelp() for options */
110 svr_opts
.rsakeyfile
= NULL
;
111 svr_opts
.dsskeyfile
= NULL
;
112 svr_opts
.bannerfile
= NULL
;
113 svr_opts
.banner
= NULL
;
115 svr_opts
.norootlogin
= 0;
116 svr_opts
.noauthpass
= 0;
117 svr_opts
.norootpass
= 0;
118 svr_opts
.inetdmode
= 0;
119 svr_opts
.portcount
= 0;
120 svr_opts
.hostkey
= NULL
;
121 svr_opts
.pidfile
= DROPBEAR_PIDFILE
;
122 #ifdef ENABLE_SVR_LOCALTCPFWD
123 svr_opts
.nolocaltcp
= 0;
125 #ifdef ENABLE_SVR_REMOTETCPFWD
126 svr_opts
.noremotetcp
= 0;
129 opts
.enable_compress
= 1;
138 #ifndef DISABLE_SYSLOG
139 svr_opts
.usingsyslog
= 1;
141 opts
.recv_window
= DEFAULT_RECV_WINDOW
;
142 opts
.keepalive_secs
= DEFAULT_KEEPALIVE
;
143 opts
.idle_timeout_secs
= DEFAULT_IDLE_TIMEOUT
;
145 #ifdef ENABLE_SVR_REMOTETCPFWD
146 opts
.listen_fwd_all
= 0;
149 for (i
= 1; i
< (unsigned int)argc
; i
++) {
151 addportandaddress(argv
[i
]);
159 dropbear_exit("Invalid null argument");
165 if (argv
[i
][0] == '-') {
166 switch (argv
[i
][1]) {
168 next
= &svr_opts
.bannerfile
;
172 next
= &svr_opts
.dsskeyfile
;
177 next
= &svr_opts
.rsakeyfile
;
183 #ifndef DISABLE_SYSLOG
185 svr_opts
.usingsyslog
= 0;
188 #ifdef ENABLE_SVR_LOCALTCPFWD
190 svr_opts
.nolocaltcp
= 1;
193 #ifdef ENABLE_SVR_REMOTETCPFWD
195 svr_opts
.noremotetcp
= 1;
198 opts
.listen_fwd_all
= 1;
203 svr_opts
.inetdmode
= 1;
210 next
= &svr_opts
.pidfile
;
213 /* motd is displayed by default, -m turns it off */
219 svr_opts
.norootlogin
= 1;
222 next
= &recv_window_arg
;
225 next
= &keepalive_arg
;
228 next
= &idle_timeout_arg
;
230 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
232 svr_opts
.noauthpass
= 1;
235 svr_opts
.norootpass
= 1;
243 /* backwards compatibility with old urandom option */
251 fprintf(stderr
, "Unknown argument %s\n", argv
[i
]);
259 /* Set up listening ports */
260 if (svr_opts
.portcount
== 0) {
261 svr_opts
.ports
[0] = m_strdup(DROPBEAR_DEFPORT
);
262 svr_opts
.addresses
[0] = m_strdup(DROPBEAR_DEFADDRESS
);
263 svr_opts
.portcount
= 1;
266 if (svr_opts
.dsskeyfile
== NULL
) {
267 svr_opts
.dsskeyfile
= DSS_PRIV_FILENAME
;
269 if (svr_opts
.rsakeyfile
== NULL
) {
270 svr_opts
.rsakeyfile
= RSA_PRIV_FILENAME
;
273 if (svr_opts
.bannerfile
) {
275 if (stat(svr_opts
.bannerfile
, &buf
) != 0) {
276 dropbear_exit("Error opening banner file '%s'",
277 svr_opts
.bannerfile
);
280 if (buf
.st_size
> MAX_BANNER_SIZE
) {
281 dropbear_exit("Banner file too large, max is %d bytes",
285 svr_opts
.banner
= buf_new(buf
.st_size
);
286 if (buf_readfile(svr_opts
.banner
, svr_opts
.bannerfile
)!=DROPBEAR_SUCCESS
) {
287 dropbear_exit("Error reading banner file '%s'",
288 svr_opts
.bannerfile
);
290 buf_setpos(svr_opts
.banner
, 0);
294 if (recv_window_arg
) {
295 opts
.recv_window
= atol(recv_window_arg
);
296 if (opts
.recv_window
== 0 || opts
.recv_window
> MAX_RECV_WINDOW
) {
297 dropbear_exit("Bad recv window '%s'", recv_window_arg
);
303 if (m_str_to_uint(keepalive_arg
, &val
) == DROPBEAR_FAILURE
) {
304 dropbear_exit("Bad keepalive '%s'", keepalive_arg
);
306 opts
.keepalive_secs
= val
;
309 if (idle_timeout_arg
) {
311 if (m_str_to_uint(idle_timeout_arg
, &val
) == DROPBEAR_FAILURE
) {
312 dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg
);
314 opts
.idle_timeout_secs
= val
;
318 static void addportandaddress(char* spec
) {
322 if (svr_opts
.portcount
< DROPBEAR_MAX_PORTS
) {
324 /* We don't free it, it becomes part of the runopt state */
325 myspec
= m_strdup(spec
);
327 /* search for ':', that separates address and port */
328 svr_opts
.ports
[svr_opts
.portcount
] = strchr(myspec
, ':');
330 if (svr_opts
.ports
[svr_opts
.portcount
] == NULL
) {
331 /* no ':' -> the whole string specifies just a port */
332 svr_opts
.ports
[svr_opts
.portcount
] = myspec
;
334 /* Split the address/port */
335 svr_opts
.ports
[svr_opts
.portcount
][0] = '\0';
336 svr_opts
.ports
[svr_opts
.portcount
]++;
337 svr_opts
.addresses
[svr_opts
.portcount
] = myspec
;
340 if (svr_opts
.addresses
[svr_opts
.portcount
] == NULL
) {
341 /* no address given -> fill in the default address */
342 svr_opts
.addresses
[svr_opts
.portcount
] = m_strdup(DROPBEAR_DEFADDRESS
);
345 if (svr_opts
.ports
[svr_opts
.portcount
][0] == '\0') {
346 /* empty port -> exit */
347 dropbear_exit("Bad port");
350 svr_opts
.portcount
++;
354 static void disablekey(int type
, const char* filename
) {
358 for (i
= 0; sshhostkey
[i
].name
!= NULL
; i
++) {
359 if (sshhostkey
[i
].val
== type
) {
360 sshhostkey
[i
].usable
= 0;
364 dropbear_log(LOG_WARNING
, "Failed reading '%s', disabling %s", filename
,
365 type
== DROPBEAR_SIGNKEY_DSS
? "DSS" : "RSA");
368 /* Must be called after syslog/etc is working */
369 void loadhostkeys() {
374 TRACE(("enter loadhostkeys"))
376 svr_opts
.hostkey
= new_sign_key();
379 type
= DROPBEAR_SIGNKEY_RSA
;
380 ret
= readhostkey(svr_opts
.rsakeyfile
, svr_opts
.hostkey
, &type
);
381 if (ret
== DROPBEAR_FAILURE
) {
382 disablekey(DROPBEAR_SIGNKEY_RSA
, svr_opts
.rsakeyfile
);
386 type
= DROPBEAR_SIGNKEY_DSS
;
387 ret
= readhostkey(svr_opts
.dsskeyfile
, svr_opts
.hostkey
, &type
);
388 if (ret
== DROPBEAR_FAILURE
) {
389 disablekey(DROPBEAR_SIGNKEY_DSS
, svr_opts
.dsskeyfile
);
395 && svr_opts
.hostkey
->dsskey
== NULL
398 && svr_opts
.hostkey
->rsakey
== NULL
401 dropbear_exit("No hostkeys available");
404 TRACE(("leave loadhostkeys"))