• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Dropbear - a SSH2 server
3  *
4  * Copyright (c) 2002,2003 Matt Johnston
5  * All rights reserved.
6  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
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
23  * SOFTWARE. */
24 
25 #include "includes.h"
26 #include "runopts.h"
27 #include "signkey.h"
28 #include "buffer.h"
29 #include "dbutil.h"
30 #include "algo.h"
31 
32 svr_runopts svr_opts; /* GLOBAL */
33 
34 static void printhelp(const char * progname);
35 static void addportandaddress(char* spec);
36 
printhelp(const char * progname)37 static void printhelp(const char * progname) {
38 
39 	fprintf(stderr, "Dropbear sshd v%s\n"
40 					"Usage: %s [options]\n"
41 					"Options are:\n"
42 					"-b bannerfile	Display the contents of bannerfile"
43 					" before user login\n"
44 					"		(default: none)\n"
45 #ifdef DROPBEAR_DSS
46 					"-d dsskeyfile	Use dsskeyfile for the dss host key\n"
47 					"		(default: %s)\n"
48 #endif
49 #ifdef DROPBEAR_RSA
50 					"-r rsakeyfile	Use rsakeyfile for the rsa host key\n"
51 					"		(default: %s)\n"
52 #endif
53 					"-F		Don't fork into background\n"
54 #ifdef DISABLE_SYSLOG
55 					"(Syslog support not compiled in, using stderr)\n"
56 #else
57 					"-E		Log to stderr rather than syslog\n"
58 #endif
59 #ifdef DO_MOTD
60 					"-m		Don't display the motd on login\n"
61 #endif
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"
66 #endif
67 #ifdef ENABLE_SVR_LOCALTCPFWD
68 					"-j		Disable local port forwarding\n"
69 #endif
70 #ifdef ENABLE_SVR_REMOTETCPFWD
71 					"-k		Disable remote port forwarding\n"
72 					"-a		Allow connections to forwarded ports from any host\n"
73 #endif
74 					"-p [address:]port\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"
79 					"		(default %s)\n"
80 #ifdef INETD_MODE
81 					"-i		Start for inetd\n"
82 #endif
83 #ifdef DEBUG_TRACE
84 					"-v		verbose\n"
85 #endif
86 					,DROPBEAR_VERSION, progname,
87 #ifdef DROPBEAR_DSS
88 					DSS_PRIV_FILENAME,
89 #endif
90 #ifdef DROPBEAR_RSA
91 					RSA_PRIV_FILENAME,
92 #endif
93 					DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE);
94 }
95 
svr_getopts(int argc,char ** argv)96 void svr_getopts(int argc, char ** argv) {
97 
98 	unsigned int i;
99 	char ** next = 0;
100 	int nextisport = 0;
101 
102 	/* see printhelp() for options */
103 	svr_opts.rsakeyfile = NULL;
104 	svr_opts.dsskeyfile = NULL;
105 	svr_opts.bannerfile = NULL;
106 	svr_opts.banner = NULL;
107 	svr_opts.forkbg = 1;
108 	svr_opts.norootlogin = 0;
109 	svr_opts.noauthpass = 0;
110 	svr_opts.norootpass = 0;
111 	svr_opts.inetdmode = 0;
112 	svr_opts.portcount = 0;
113 	svr_opts.hostkey = NULL;
114 	svr_opts.pidfile = DROPBEAR_PIDFILE;
115 #ifdef ENABLE_SVR_LOCALTCPFWD
116 	svr_opts.nolocaltcp = 0;
117 #endif
118 #ifdef ENABLE_SVR_REMOTETCPFWD
119 	svr_opts.noremotetcp = 0;
120 #endif
121 	/* not yet
122 	opts.ipv4 = 1;
123 	opts.ipv6 = 1;
124 	*/
125 #ifdef DO_MOTD
126 	svr_opts.domotd = 1;
127 #endif
128 #ifndef DISABLE_SYSLOG
129 	svr_opts.usingsyslog = 1;
130 #endif
131 #ifdef ENABLE_SVR_REMOTETCPFWD
132 	opts.listen_fwd_all = 0;
133 #endif
134 
135 	for (i = 1; i < (unsigned int)argc; i++) {
136 		if (nextisport) {
137 			addportandaddress(argv[i]);
138 			nextisport = 0;
139 			continue;
140 		}
141 
142 		if (next) {
143 			*next = argv[i];
144 			if (*next == NULL) {
145 				dropbear_exit("Invalid null argument");
146 			}
147 			next = 0x00;
148 			continue;
149 		}
150 
151 		if (argv[i][0] == '-') {
152 			switch (argv[i][1]) {
153 				case 'b':
154 					next = &svr_opts.bannerfile;
155 					break;
156 #ifdef DROPBEAR_DSS
157 				case 'd':
158 					next = &svr_opts.dsskeyfile;
159 					break;
160 #endif
161 #ifdef DROPBEAR_RSA
162 				case 'r':
163 					next = &svr_opts.rsakeyfile;
164 					break;
165 #endif
166 				case 'F':
167 					svr_opts.forkbg = 0;
168 					break;
169 #ifndef DISABLE_SYSLOG
170 				case 'E':
171 					svr_opts.usingsyslog = 0;
172 					break;
173 #endif
174 #ifdef ENABLE_SVR_LOCALTCPFWD
175 				case 'j':
176 					svr_opts.nolocaltcp = 1;
177 					break;
178 #endif
179 #ifdef ENABLE_SVR_REMOTETCPFWD
180 				case 'k':
181 					svr_opts.noremotetcp = 1;
182 					break;
183 				case 'a':
184 					opts.listen_fwd_all = 1;
185 					break;
186 #endif
187 #ifdef INETD_MODE
188 				case 'i':
189 					svr_opts.inetdmode = 1;
190 					break;
191 #endif
192 				case 'p':
193 				  nextisport = 1;
194 				  break;
195 				case 'P':
196 					next = &svr_opts.pidfile;
197 					break;
198 #ifdef DO_MOTD
199 				/* motd is displayed by default, -m turns it off */
200 				case 'm':
201 					svr_opts.domotd = 0;
202 					break;
203 #endif
204 				case 'w':
205 					svr_opts.norootlogin = 1;
206 					break;
207 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
208 				case 's':
209 					svr_opts.noauthpass = 1;
210 					break;
211 				case 'g':
212 					svr_opts.norootpass = 1;
213 					break;
214 #endif
215 				case 'h':
216 					printhelp(argv[0]);
217 					exit(EXIT_FAILURE);
218 					break;
219 #ifdef DEBUG_TRACE
220 				case 'v':
221 					debug_trace = 1;
222 					break;
223 #endif
224 				default:
225 					fprintf(stderr, "Unknown argument %s\n", argv[i]);
226 					printhelp(argv[0]);
227 					exit(EXIT_FAILURE);
228 					break;
229 			}
230 		}
231 	}
232 
233 	/* Set up listening ports */
234 	if (svr_opts.portcount == 0) {
235 		svr_opts.ports[0] = m_strdup(DROPBEAR_DEFPORT);
236 		svr_opts.addresses[0] = m_strdup(DROPBEAR_DEFADDRESS);
237 		svr_opts.portcount = 1;
238 	}
239 
240 	if (svr_opts.dsskeyfile == NULL) {
241 		svr_opts.dsskeyfile = DSS_PRIV_FILENAME;
242 	}
243 	if (svr_opts.rsakeyfile == NULL) {
244 		svr_opts.rsakeyfile = RSA_PRIV_FILENAME;
245 	}
246 
247 	if (svr_opts.bannerfile) {
248 		struct stat buf;
249 		if (stat(svr_opts.bannerfile, &buf) != 0) {
250 			dropbear_exit("Error opening banner file '%s'",
251 					svr_opts.bannerfile);
252 		}
253 
254 		if (buf.st_size > MAX_BANNER_SIZE) {
255 			dropbear_exit("Banner file too large, max is %d bytes",
256 					MAX_BANNER_SIZE);
257 		}
258 
259 		svr_opts.banner = buf_new(buf.st_size);
260 		if (buf_readfile(svr_opts.banner, svr_opts.bannerfile)!=DROPBEAR_SUCCESS) {
261 			dropbear_exit("Error reading banner file '%s'",
262 					svr_opts.bannerfile);
263 		}
264 		buf_setpos(svr_opts.banner, 0);
265 	}
266 
267 }
268 
addportandaddress(char * spec)269 static void addportandaddress(char* spec) {
270 
271 	char *myspec = NULL;
272 
273 	if (svr_opts.portcount < DROPBEAR_MAX_PORTS) {
274 
275 		/* We don't free it, it becomes part of the runopt state */
276 		myspec = m_strdup(spec);
277 
278 		/* search for ':', that separates address and port */
279 		svr_opts.ports[svr_opts.portcount] = strchr(myspec, ':');
280 
281 		if (svr_opts.ports[svr_opts.portcount] == NULL) {
282 			/* no ':' -> the whole string specifies just a port */
283 			svr_opts.ports[svr_opts.portcount] = myspec;
284 		} else {
285 			/* Split the address/port */
286 			svr_opts.ports[svr_opts.portcount][0] = '\0';
287 			svr_opts.ports[svr_opts.portcount]++;
288 			svr_opts.addresses[svr_opts.portcount] = myspec;
289 		}
290 
291 		if (svr_opts.addresses[svr_opts.portcount] == NULL) {
292 			/* no address given -> fill in the default address */
293 			svr_opts.addresses[svr_opts.portcount] = m_strdup(DROPBEAR_DEFADDRESS);
294 		}
295 
296 		if (svr_opts.ports[svr_opts.portcount][0] == '\0') {
297 			/* empty port -> exit */
298 			dropbear_exit("Bad port");
299 		}
300 
301 		svr_opts.portcount++;
302 	}
303 }
304 
disablekey(int type,const char * filename)305 static void disablekey(int type, const char* filename) {
306 
307 	int i;
308 
309 	for (i = 0; sshhostkey[i].name != NULL; i++) {
310 		if (sshhostkey[i].val == type) {
311 			sshhostkey[i].usable = 0;
312 			break;
313 		}
314 	}
315 	dropbear_log(LOG_WARNING, "Failed reading '%s', disabling %s", filename,
316 			type == DROPBEAR_SIGNKEY_DSS ? "DSS" : "RSA");
317 }
318 
319 /* Must be called after syslog/etc is working */
loadhostkeys()320 void loadhostkeys() {
321 
322 	int ret;
323 	int type;
324 
325 	TRACE(("enter loadhostkeys"))
326 
327 	svr_opts.hostkey = new_sign_key();
328 
329 #ifdef DROPBEAR_RSA
330 	type = DROPBEAR_SIGNKEY_RSA;
331 	ret = readhostkey(svr_opts.rsakeyfile, svr_opts.hostkey, &type);
332 	if (ret == DROPBEAR_FAILURE) {
333 		disablekey(DROPBEAR_SIGNKEY_RSA, svr_opts.rsakeyfile);
334 	}
335 #endif
336 #ifdef DROPBEAR_DSS
337 	type = DROPBEAR_SIGNKEY_DSS;
338 	ret = readhostkey(svr_opts.dsskeyfile, svr_opts.hostkey, &type);
339 	if (ret == DROPBEAR_FAILURE) {
340 		disablekey(DROPBEAR_SIGNKEY_DSS, svr_opts.dsskeyfile);
341 	}
342 #endif
343 
344 	if ( 1
345 #ifdef DROPBEAR_DSS
346 		&& svr_opts.hostkey->dsskey == NULL
347 #endif
348 #ifdef DROPBEAR_RSA
349 		&& svr_opts.hostkey->rsakey == NULL
350 #endif
351 		) {
352 		dropbear_exit("No hostkeys available");
353 	}
354 
355 	TRACE(("leave loadhostkeys"))
356 }
357