1 | /* |
---|
2 | |
---|
3 | sshd.c |
---|
4 | |
---|
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> |
---|
6 | |
---|
7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
---|
8 | All rights reserved |
---|
9 | |
---|
10 | Created: Fri Mar 17 17:09:28 1995 ylo |
---|
11 | |
---|
12 | This program is the ssh daemon. It listens for connections from clients, and |
---|
13 | performs authentication, executes use commands or shell, and forwards |
---|
14 | information to/from the application to the user client over an encrypted |
---|
15 | connection. This can also handle forwarding of X11, TCP/IP, and authentication |
---|
16 | agent connections. |
---|
17 | |
---|
18 | */ |
---|
19 | |
---|
20 | /* |
---|
21 | * $Id: sshd.c,v 1.18 1999-03-27 01:59:28 ghudson Exp $ |
---|
22 | * $Log: not supported by cvs2svn $ |
---|
23 | * Revision 1.17 1999/03/16 19:03:38 danw |
---|
24 | * log a debugging error if al_acct_create fails |
---|
25 | * |
---|
26 | * Revision 1.16 1999/03/08 18:20:11 danw |
---|
27 | * merge changes |
---|
28 | * |
---|
29 | * Revision 1.15 1999/02/27 17:08:21 ghudson |
---|
30 | * Teach sshd how to switch on SIGUSR1/SIGUSR2. |
---|
31 | * Note: the current implementation only works with LIBWRAP defined, |
---|
32 | * since that's how we build it. |
---|
33 | * |
---|
34 | * Revision 1.14 1998/06/30 21:10:02 danw |
---|
35 | * put xauthority data in /tmp, not afs |
---|
36 | * |
---|
37 | * Revision 1.13 1998/05/13 20:18:55 danw |
---|
38 | * merge in changes from 1.2.23 |
---|
39 | * |
---|
40 | * Revision 1.12 1998/04/25 23:15:56 ghudson |
---|
41 | * Take advantage of relaxed al_acct_create() contract. |
---|
42 | * |
---|
43 | * Revision 1.11 1998/04/09 22:51:48 ghudson |
---|
44 | * Support local accounts as determined by libal. |
---|
45 | * |
---|
46 | * Revision 1.10 1998/03/12 20:37:12 danw |
---|
47 | * recheck pw->pw_dir after al_acct_create in case we got a temp homedir |
---|
48 | * |
---|
49 | * Revision 1.9 1998/03/01 16:12:59 danw |
---|
50 | * Use xmalloc, not malloc. (pointed out by mhpower) |
---|
51 | * |
---|
52 | * Revision 1.8 1998/02/28 17:58:31 danw |
---|
53 | * Don't use packet_disconnect for `you are not allowed to log in here' |
---|
54 | * |
---|
55 | * Revision 1.7 1998/02/02 23:20:15 danw |
---|
56 | * use our DEFAULT_PATH, not the OS's unless the builder overrides it on |
---|
57 | * the command line. |
---|
58 | * |
---|
59 | * Revision 1.6 1998/01/24 01:47:26 danw |
---|
60 | * merge in changes for 1.2.22 |
---|
61 | * |
---|
62 | * Revision 1.5 1998/01/01 18:18:21 danw |
---|
63 | * Don't set KRB5CCNAME if the user didn't get tickets |
---|
64 | * |
---|
65 | * Revision 1.4 1997/11/19 20:44:45 danw |
---|
66 | * do chown later |
---|
67 | * |
---|
68 | * Revision 1.3 1997/11/15 00:04:20 danw |
---|
69 | * Use atexit() functions to destroy tickets and call al_acct_revert. |
---|
70 | * Work around Solaris lossage with libucb and grantpt. |
---|
71 | * |
---|
72 | * Revision 1.2 1997/11/12 21:16:18 danw |
---|
73 | * Athena-login changes (including some krb4 stuff) |
---|
74 | * |
---|
75 | * Revision 1.1.1.1 1997/10/17 22:26:00 danw |
---|
76 | * Import of ssh 1.2.21 |
---|
77 | * |
---|
78 | * Revision 1.1.1.2 1998/01/24 01:25:18 danw |
---|
79 | * Import of ssh 1.2.22 |
---|
80 | * |
---|
81 | * Revision 1.1.1.3 1998/05/13 19:11:09 danw |
---|
82 | * Import of ssh 1.2.23 |
---|
83 | * |
---|
84 | * Revision 1.1.1.4 1999/03/08 17:43:02 danw |
---|
85 | * Import of ssh 1.2.26 |
---|
86 | * |
---|
87 | * Revision 1.55 1998/07/08 14:55:22 tri |
---|
88 | * Fixed version negotiation so, that ssh 2 |
---|
89 | * compatibility is even remotedly possible. |
---|
90 | * |
---|
91 | * Revision 1.54 1998/07/08 00:48:46 kivinen |
---|
92 | * Added better HPUX TCB auth support. Added SGI proj support. |
---|
93 | * Changed to use match_host in the allow/deny checking. Changed |
---|
94 | * to use PASSWD_PATH. Added checking that if allow/deny group is |
---|
95 | * set then the group must exists. |
---|
96 | * |
---|
97 | * Revision 1.53 1998/06/11 00:11:24 kivinen |
---|
98 | * Added ENABLE_SO_LINGER ifdef. Added username to /bin/password |
---|
99 | * commands. Added user@host support. |
---|
100 | * |
---|
101 | * Revision 1.52 1998/05/23 20:28:12 kivinen |
---|
102 | * Changed () -> (void). Added HAVE_OSF1_C2_SECURITY include |
---|
103 | * files. Added days_before_{account,password}_expires support. |
---|
104 | * Added chalnecho TIS authentication server response code |
---|
105 | * support. Added call to osf1c2_check_account_and_terminal |
---|
106 | * function. Added SSH_BINDIR to path read from |
---|
107 | * /etc/default/login. Fixed BSDI login_getclass code for BSDI |
---|
108 | * 2.1. |
---|
109 | * |
---|
110 | * Revision 1.51 1998/05/11 18:51:07 kivinen |
---|
111 | * Fixed AIX authstate code. |
---|
112 | * |
---|
113 | * Revision 1.50 1998/04/30 01:58:40 kivinen |
---|
114 | * Fixed osflim handling so that now it allows setting resource |
---|
115 | * to 0. Added -V option (for ssh version 2 compat mode). Added |
---|
116 | * LIBWRAP code to also when in debugging mode. Added BSDI |
---|
117 | * setusercontext code. |
---|
118 | * |
---|
119 | * Revision 1.49 1998/04/17 00:42:36 kivinen |
---|
120 | * Freebsd login capabilities support. Added REMOTEUSER |
---|
121 | * environment variable setting. Changed locked account checking |
---|
122 | * so that it will not care if the account is locked if |
---|
123 | * kerberos_or_local_password is not set. Added nologin-allow |
---|
124 | * support. Added setting of AUTHSTATE and KRB5CCNAME enviroment |
---|
125 | * variables if AIX authenticate() function is used. |
---|
126 | * |
---|
127 | * Revision 1.48 1998/03/27 17:05:01 kivinen |
---|
128 | * Added SIGDANGER code. Fixed kerberos initialization code so |
---|
129 | * ssh will check the error codes of initialization function. |
---|
130 | * added ignore_root_rhosts code. Moved initgroups before closing |
---|
131 | * all filedescriptors. |
---|
132 | * |
---|
133 | * Revision 1.47 1998/01/03 06:42:43 kivinen |
---|
134 | * Added allow/deny groups option support. |
---|
135 | * |
---|
136 | * Revision 1.46 1998/01/02 06:39:36 kivinen |
---|
137 | * Added new mail checking. Added expiration checkind for bsdi, |
---|
138 | * and warning when password is about to expire. Fixed kerberos |
---|
139 | * ticket name handling. Added support for XAuthLocation option. |
---|
140 | * Added support for login capabilities for bsdi, only support |
---|
141 | * ignorelogin option. |
---|
142 | * Added osfc2 resource limit setting. |
---|
143 | * |
---|
144 | * Revision 1.45 1997/10/01 19:16:32 ylo |
---|
145 | * Clarified error message about xauth not being in path. |
---|
146 | * |
---|
147 | * Revision 1.44 1997/05/08 03:06:51 kivinen |
---|
148 | * Fixed sighup handling (added select before accept, changed |
---|
149 | * execv to execvp so sshd is searched from path). |
---|
150 | * |
---|
151 | * Revision 1.43 1997/04/27 21:51:11 kivinen |
---|
152 | * Added F-SECURE stuff. Added {Allow,Deny}Forwarding{To,Port} |
---|
153 | * feature. Added {Allow,Deny}Users feature from Steve Kann |
---|
154 | * <stevek@SteveK.COM>. |
---|
155 | * |
---|
156 | * Revision 1.42 1997/04/23 00:05:35 kivinen |
---|
157 | * Added ifdefs around password expiration and inactivity checks, |
---|
158 | * because some systems dont have sp_expire and sp_inact fields. |
---|
159 | * |
---|
160 | * Revision 1.41 1997/04/21 01:05:56 kivinen |
---|
161 | * Added waitpid loop to main_sigchld_handler if we have it. |
---|
162 | * Added check to pty_cleanup_proc so it will not cleanup pty |
---|
163 | * twice. |
---|
164 | * Changed argument to server_loop from ttyname to |
---|
165 | * cleanup_context. |
---|
166 | * |
---|
167 | * Revision 1.40 1997/04/17 04:04:58 kivinen |
---|
168 | * Removed extra variable err. |
---|
169 | * |
---|
170 | * Revision 1.39 1997/04/17 04:04:13 kivinen |
---|
171 | * Added fatal: to all errors that cause sshd to exit. |
---|
172 | * Added resetting of SIGCHLD before running libwrap code. |
---|
173 | * Moved pty/pipe closing to server_loop. Added ttyname argument |
---|
174 | * to server_loop. |
---|
175 | * Server_loop will also now release the pty if it is allocated. |
---|
176 | * |
---|
177 | * Revision 1.38 1997/04/05 22:03:38 kivinen |
---|
178 | * Added check that userfile_get_des_1_magic_phrase succeeded, |
---|
179 | * before using the passphrase. Moved closing of pty after the |
---|
180 | * pty_release. |
---|
181 | * |
---|
182 | * Revision 1.37 1997/04/05 17:28:31 ylo |
---|
183 | * Added a workaround for the Windows SSH problem with X11 |
---|
184 | * forwarding. |
---|
185 | * |
---|
186 | * Revision 1.36 1997/03/27 05:59:50 kivinen |
---|
187 | * Fixed bug in HAVE_USERSEC_H code. |
---|
188 | * |
---|
189 | * Revision 1.35 1997/03/27 03:12:22 kivinen |
---|
190 | * Added kerberos patches from Glenn Machin. |
---|
191 | * Added USELOGIN patches from Brian Cully. |
---|
192 | * |
---|
193 | * Revision 1.34 1997/03/26 05:32:42 kivinen |
---|
194 | * Added idle_timeout variable. |
---|
195 | * If debug_flag is given set rsa to verbose. |
---|
196 | * Changed uid 0 to bee UID_ROOT. |
---|
197 | * |
---|
198 | * Revision 1.33 1997/03/25 05:48:29 kivinen |
---|
199 | * Implemented SilentDeny and umask options. Added HAVE_DAEMON |
---|
200 | * support. |
---|
201 | * Moved LIBWRAP code to child. |
---|
202 | * Moved closing of sockets/pipes out from server_loop. |
---|
203 | * |
---|
204 | * Revision 1.32 1997/03/19 23:04:43 kivinen |
---|
205 | * Fixed typo. |
---|
206 | * |
---|
207 | * Revision 1.31 1997/03/19 21:17:57 kivinen |
---|
208 | * Added some errno printing to all fatal calls. |
---|
209 | * Added SSH_ORIGINAL_COMMAND environment variable setting. It |
---|
210 | * will have the original command from the network when using |
---|
211 | * forced command. It can be used to get arguments for forced |
---|
212 | * command. |
---|
213 | * |
---|
214 | * Revision 1.30 1997/03/19 19:25:57 kivinen |
---|
215 | * Added input buffer clearing for error conditions, so packet.c |
---|
216 | * can check that buffer must be empty before new packet is read |
---|
217 | * in. |
---|
218 | * |
---|
219 | * Revision 1.29 1997/03/19 17:53:17 kivinen |
---|
220 | * Added more ETC_SHADOW support and SECURE_RPC, SECURE_NFS and |
---|
221 | * NIS_PLUS support from Andy Polyakov <appro@fy.chalmers.se>. |
---|
222 | * Added TIS authentication code from Andre April |
---|
223 | * <Andre.April@cediti.be>. |
---|
224 | * Moved authentication fail loop to do_authentication_fail_loop |
---|
225 | * function. Added checks that username isn't longer than 255 |
---|
226 | * characters. |
---|
227 | * Changed do_authentication to get cipher_type, so it can |
---|
228 | * disable RhostsRsa authentication if using unsecure cipher |
---|
229 | * (NONE, or ARCFOUR). |
---|
230 | * Changed order of environment variables set to child, because |
---|
231 | * digital unixes telnet dumps core if USER is the first |
---|
232 | * environment variable set. |
---|
233 | * Added code that will set all ip-address to xauth so it should |
---|
234 | * work for multihosted machines too. Dont use xauth add |
---|
235 | * host/unix:0 on crays, because it complains about it. Patch |
---|
236 | * from Arne Henrik Juul <arnej@imf.unit.no> |
---|
237 | * |
---|
238 | * Revision 1.28 1996/11/24 08:26:15 kivinen |
---|
239 | * Added SSHD_NO_{PORT,X11}_FORWARDING support. |
---|
240 | * |
---|
241 | * Revision 1.27 1996/11/04 06:35:01 ylo |
---|
242 | * Updated processing of check_emulation output. |
---|
243 | * |
---|
244 | * Revision 1.26 1996/10/29 22:46:25 kivinen |
---|
245 | * log -> log_msg. Added old agent emulation code (disable agent |
---|
246 | * forwarding if the other end is too old). |
---|
247 | * |
---|
248 | * Revision 1.25 1996/10/23 15:59:13 ttsalo |
---|
249 | * Changed BINDIR's name to SSH_BINDIR to prevent conflicts |
---|
250 | * |
---|
251 | * Revision 1.24 1996/10/21 16:35:23 ttsalo |
---|
252 | * Removed some fd auth code |
---|
253 | * |
---|
254 | * Revision 1.23 1996/10/21 16:18:34 ttsalo |
---|
255 | * Had to remove BINDIR from line 2518 |
---|
256 | * |
---|
257 | * Revision 1.22 1996/10/20 16:19:36 ttsalo |
---|
258 | * Added global variable 'original_real_uid' and it's initialization |
---|
259 | * |
---|
260 | * Revision 1.20 1996/09/27 17:19:16 ylo |
---|
261 | * Merged ultrix patches from Corey Satten. |
---|
262 | * |
---|
263 | * Revision 1.19 1996/09/22 22:38:49 ylo |
---|
264 | * Added endgrent() before closing all file descriptors. |
---|
265 | * |
---|
266 | * Revision 1.18 1996/09/08 17:40:31 ttsalo |
---|
267 | * BSD4.4Lite's _PATH_DEFPATH is checked when defining DEFAULT_PATH. |
---|
268 | * (Patch from Andrey A. Chernov <ache@lsd.relcom.eu.net>) |
---|
269 | * |
---|
270 | * Revision 1.17 1996/08/29 14:51:23 ttsalo |
---|
271 | * Agent-socket directory handling implemented |
---|
272 | * |
---|
273 | * Revision 1.16 1996/08/22 22:16:24 ylo |
---|
274 | * Log remote commands executed by root, and log the fact that a |
---|
275 | * remote command was executed by an ordinary user, but not the |
---|
276 | * actual command (for privacy reasons). |
---|
277 | * |
---|
278 | * Revision 1.15 1996/08/16 02:47:18 ylo |
---|
279 | * Log root logins at LOG_NOTICE. |
---|
280 | * |
---|
281 | * Revision 1.14 1996/08/13 09:04:23 ttsalo |
---|
282 | * Home directory, .ssh and .ssh/authorized_keys are now |
---|
283 | * checked for wrong owner and group & world writeability. |
---|
284 | * |
---|
285 | * Revision 1.13 1996/08/13 00:23:31 ylo |
---|
286 | * When doing X11 forwarding, check the existence of xauth and |
---|
287 | * deny forwarding if it doesn't exist. This makes copying |
---|
288 | * binaries compiled on one system to other systems easier. |
---|
289 | * |
---|
290 | * Run /etc/sshrc with /bin/sh instead of the user's shell. |
---|
291 | * |
---|
292 | * Revision 1.12 1996/07/29 04:58:54 ylo |
---|
293 | * Add xauth data also for `hostname`/unix:$display as some X |
---|
294 | * servers actually seem to use this version. (Kludge to work |
---|
295 | * around X11 bug.) |
---|
296 | * |
---|
297 | * Revision 1.11 1996/07/15 23:21:55 ylo |
---|
298 | * Don't allow more than five password authentication attempts, |
---|
299 | * and log attempts after the first one. |
---|
300 | * |
---|
301 | * Revision 1.10 1996/07/12 07:28:02 ttsalo |
---|
302 | * Small ultrix patch |
---|
303 | * |
---|
304 | * Revision 1.9 1996/06/05 17:57:34 ylo |
---|
305 | * If /etc/nologin exists, print that fact in plain text before |
---|
306 | * printing the actual contents. I am getting too many |
---|
307 | * complaints about it. |
---|
308 | * |
---|
309 | * Revision 1.8 1996/06/03 19:25:49 ylo |
---|
310 | * Fixed a typo. |
---|
311 | * |
---|
312 | * Revision 1.7 1996/05/29 07:41:46 ylo |
---|
313 | * Added arguments to userfile_init. |
---|
314 | * |
---|
315 | * Revision 1.6 1996/05/29 07:16:38 ylo |
---|
316 | * Disallow any user names that start with a '-' or '+' (or '@', |
---|
317 | * just to be sure). There is some indication that getpw* might |
---|
318 | * returns such names on some systems with NIS. Ouuuch! |
---|
319 | * |
---|
320 | * Revision 1.5 1996/05/28 16:41:14 ylo |
---|
321 | * Merged Cray patches from Wayne Schroeder. |
---|
322 | * Use setsid instead of setpgrp on ultrix. |
---|
323 | * |
---|
324 | * Revision 1.4 1996/04/26 00:22:51 ylo |
---|
325 | * Improved error messages related to reading host key. |
---|
326 | * Fixed ip addr in "Closing connection" message. |
---|
327 | * |
---|
328 | * Revision 1.3 1996/04/22 23:49:47 huima |
---|
329 | * Changed protocol version to 1.4, added calls to emulate module. |
---|
330 | * |
---|
331 | * Revision 1.2 1996/02/18 21:49:51 ylo |
---|
332 | * Moved userfile_uninit to proper place. |
---|
333 | * Use setluid if it exists (at least OSF/1). |
---|
334 | * |
---|
335 | * Revision 1.1.1.1 1996/02/18 21:38:13 ylo |
---|
336 | * Imported ssh-1.2.13. |
---|
337 | * |
---|
338 | * Revision 1.31 1995/10/02 01:28:59 ylo |
---|
339 | * Include sys/syslog.h if NEED_SYS_SYSLOG_H. |
---|
340 | * Print proper ETCDIR in usage(). |
---|
341 | * |
---|
342 | * Revision 1.30 1995/09/27 02:54:43 ylo |
---|
343 | * Fixed a minor error. |
---|
344 | * |
---|
345 | * Revision 1.29 1995/09/27 02:49:06 ylo |
---|
346 | * Fixed syntax errors. |
---|
347 | * |
---|
348 | * Revision 1.28 1995/09/27 02:18:51 ylo |
---|
349 | * Added support for SCO unix. |
---|
350 | * Added support for .hushlogin. |
---|
351 | * Read $HOME/.environment. |
---|
352 | * Pass X11 proto and cookie in stdin instead of command line. |
---|
353 | * Added support for $HOME/.ssh/rc and /etc/sshrc. |
---|
354 | * |
---|
355 | * Revision 1.27 1995/09/25 00:03:53 ylo |
---|
356 | * Added screen number. |
---|
357 | * Don't display motd and login time if executing a command. |
---|
358 | * |
---|
359 | * Revision 1.26 1995/09/22 22:22:34 ylo |
---|
360 | * Fixed a bug in the new environment code. |
---|
361 | * |
---|
362 | * Revision 1.25 1995/09/21 17:16:49 ylo |
---|
363 | * Fixes to libwrap code. |
---|
364 | * Fixed problem in wait() in key regeneration. Now only |
---|
365 | * ackquires light noise at regeneration. |
---|
366 | * Support for ignore_rhosts. |
---|
367 | * Don't use X11 forwarding with spoofing if no xauth. |
---|
368 | * Rewrote the code to initialize the environment in the child. |
---|
369 | * Added code to read /etc/environment into child environment. |
---|
370 | * Fixed setpcred argument type. |
---|
371 | * |
---|
372 | * Revision 1.24 1995/09/11 17:35:53 ylo |
---|
373 | * Added libwrap support. |
---|
374 | * Log daemon name without path. |
---|
375 | * |
---|
376 | * Revision 1.23 1995/09/10 23:43:32 ylo |
---|
377 | * Added a newline in xauth message. |
---|
378 | * |
---|
379 | * Revision 1.22 1995/09/10 23:29:43 ylo |
---|
380 | * Renamed sigchld_handler main_sigchld_handler to avoid |
---|
381 | * conflict. |
---|
382 | * |
---|
383 | * Revision 1.21 1995/09/10 23:26:53 ylo |
---|
384 | * Child xauth line printed with fprintf instead of debug(). |
---|
385 | * |
---|
386 | * Revision 1.20 1995/09/10 22:43:17 ylo |
---|
387 | * Added uid-swapping stuff. |
---|
388 | * Moved do_session to serverloop.c and renamed it server_loop. |
---|
389 | * Changed SIGCHLD handling. |
---|
390 | * Merged OSF/1 C2 security stuff. |
---|
391 | * |
---|
392 | * Revision 1.19 1995/09/09 21:26:47 ylo |
---|
393 | * /m/shadows/u2/users/ylo/ssh/README |
---|
394 | * |
---|
395 | * Revision 1.18 1995/09/06 19:53:19 ylo |
---|
396 | * Fixed spelling of fascist. |
---|
397 | * |
---|
398 | * Revision 1.17 1995/09/06 16:02:40 ylo |
---|
399 | * Added /usr/bin/X11 to default DEFAULT_PATH. |
---|
400 | * Fixed inetd_flag & debug_flag together. |
---|
401 | * Fixed -i. |
---|
402 | * |
---|
403 | * Revision 1.16 1995/08/31 09:43:14 ylo |
---|
404 | * Fixed LOGNAME. |
---|
405 | * |
---|
406 | * Revision 1.15 1995/08/31 09:26:22 ylo |
---|
407 | * Copy struct pw. |
---|
408 | * Use socketpairs for communicating with the shell/command. |
---|
409 | * Use same socket for stdin and stdout. (may help rdist) |
---|
410 | * Put LOGNAME in environment. |
---|
411 | * Run xauth directly, without the shell in between. |
---|
412 | * Fixed the HPSUX kludge. |
---|
413 | * |
---|
414 | * Revision 1.14 1995/08/29 22:36:12 ylo |
---|
415 | * Added SIGHUP handling. Added SIGTERM and SIGQUIT handling. |
---|
416 | * Permit root login if forced command. |
---|
417 | * Added DenyHosts, AllowHosts. Added PrintMotd. |
---|
418 | * New file descriptor code. |
---|
419 | * Use HPSUX and SIGCHLD kludges only on HPUX. |
---|
420 | * |
---|
421 | * Revision 1.13 1995/08/22 14:06:11 ylo |
---|
422 | * Added /usr/local/bin in default DEFAULT_PATH. |
---|
423 | * |
---|
424 | * Revision 1.12 1995/08/21 23:33:48 ylo |
---|
425 | * Added "-f conffile" option. |
---|
426 | * Added support for the server configuration file. |
---|
427 | * Added allow/deny host code. |
---|
428 | * Added code to optionally deny root logins. |
---|
429 | * Added code to configure allowed authentication methods. |
---|
430 | * Changes to log initialization arguments. |
---|
431 | * Eliminated NO_RHOSTS_AUTHENTICATION. |
---|
432 | * |
---|
433 | * Revision 1.11 1995/08/18 22:58:06 ylo |
---|
434 | * Added support for O_NONBLOCK_BROKEN. |
---|
435 | * Added support for TTY_GROUP. |
---|
436 | * |
---|
437 | * Revision 1.10 1995/07/27 02:19:09 ylo |
---|
438 | * Tell packet_set_encryption_key that we are the server. |
---|
439 | * |
---|
440 | * Temporary kludge to make TCP/IP port forwarding work |
---|
441 | * properly. This kludge will increase idle CPU usage because |
---|
442 | * sshd wakes up every 300ms. |
---|
443 | * |
---|
444 | * Revision 1.9 1995/07/27 00:41:34 ylo |
---|
445 | * If DEFAULT_PATH defined by configure, use that value. |
---|
446 | * |
---|
447 | * Revision 1.8 1995/07/26 23:21:06 ylo |
---|
448 | * Removed include version.h. Added include mpaux.h. |
---|
449 | * |
---|
450 | * Print software version with -d. |
---|
451 | * |
---|
452 | * Added support for protocol version 1.1. Fixes minor security |
---|
453 | * problems, and updates the protocol to match the draft RFC. |
---|
454 | * Compatibility code makes it possible to use old clients with |
---|
455 | * this server. |
---|
456 | * |
---|
457 | * Revision 1.7 1995/07/16 01:01:41 ylo |
---|
458 | * Removed hostname argument from record_logout. |
---|
459 | * Added call to pty_release. |
---|
460 | * Set tty mode depending on whether we have tty group. |
---|
461 | * |
---|
462 | * Revision 1.6 1995/07/15 22:27:04 ylo |
---|
463 | * Added printing of /etc/motd. |
---|
464 | * |
---|
465 | * Revision 1.5 1995/07/15 21:41:04 ylo |
---|
466 | * Changed the HPSUX kludge (child_has_terminated). It caused |
---|
467 | * sshd to busy-loop if the program exited but there were open |
---|
468 | * connections. |
---|
469 | * |
---|
470 | * Revision 1.4 1995/07/14 23:37:43 ylo |
---|
471 | * Limit outgoing packet size to 512 bytes for interactive |
---|
472 | * connections. |
---|
473 | * |
---|
474 | * Revision 1.3 1995/07/13 17:33:17 ylo |
---|
475 | * Only record the pid in /etc/sshd_pid if running without the |
---|
476 | * debugging flag. |
---|
477 | * |
---|
478 | * Revision 1.2 1995/07/13 01:40:47 ylo |
---|
479 | * Removed "Last modified" header. |
---|
480 | * Added cvs log. |
---|
481 | * |
---|
482 | * $Endlog$ |
---|
483 | */ |
---|
484 | |
---|
485 | #include "includes.h" |
---|
486 | #include <gmp.h> |
---|
487 | #include "xmalloc.h" |
---|
488 | #include "rsa.h" |
---|
489 | #include "ssh.h" |
---|
490 | #include "pty.h" |
---|
491 | #include "packet.h" |
---|
492 | #include "buffer.h" |
---|
493 | #include "cipher.h" |
---|
494 | #include "mpaux.h" |
---|
495 | #include "servconf.h" |
---|
496 | #include "userfile.h" |
---|
497 | #include "emulate.h" |
---|
498 | #ifdef HAVE_USERSEC_H |
---|
499 | #include <usersec.h> |
---|
500 | #endif /* HAVE_USERSEC_H */ |
---|
501 | #ifdef HAVE_ULIMIT_H |
---|
502 | #include <ulimit.h> |
---|
503 | #endif /* HAVE_ULIMIT_H */ |
---|
504 | #ifdef HAVE_HPUX_TCB_AUTH |
---|
505 | #include <sys/types.h> |
---|
506 | #include <hpsecurity.h> |
---|
507 | #include <prot.h> |
---|
508 | #endif |
---|
509 | #ifdef HAVE_ETC_SHADOW |
---|
510 | #ifdef HAVE_SHADOW_H |
---|
511 | #include <shadow.h> |
---|
512 | #endif /* HAVE_SHADOW_H */ |
---|
513 | #ifndef SHADOW |
---|
514 | #define SHADOW "/etc/shadow" |
---|
515 | #endif |
---|
516 | #endif /* HAVE_ETC_SHADOW */ |
---|
517 | |
---|
518 | #ifdef HAVE_OSF1_C2_SECURITY |
---|
519 | #include <prot.h> |
---|
520 | #endif /* HAVE_OSF1_C2_SECURITY */ |
---|
521 | |
---|
522 | #if defined (__bsdi__) && _BSDI_VERSION >= 199510 |
---|
523 | #include <tzfile.h> |
---|
524 | #include <login_cap.h> |
---|
525 | #endif /* __bsdi__ && _BSDI_VERISION >= 199510 */ |
---|
526 | |
---|
527 | #ifdef LIBWRAP |
---|
528 | #include <tcpd.h> |
---|
529 | #include <syslog.h> |
---|
530 | #ifdef NEED_SYS_SYSLOG_H |
---|
531 | #include <sys/syslog.h> |
---|
532 | #endif /* NEED_SYS_SYSLOG_H */ |
---|
533 | int allow_severity = LOG_INFO; |
---|
534 | int deny_severity = LOG_WARNING; |
---|
535 | #endif /* LIBWRAP */ |
---|
536 | |
---|
537 | #ifdef CRAY |
---|
538 | #include <udb.h> |
---|
539 | #include <unistd.h> |
---|
540 | #include <sys/category.h> |
---|
541 | extern char *setlimits(); |
---|
542 | #endif |
---|
543 | |
---|
544 | #ifdef HAVE_SGI_PROJ_H |
---|
545 | #include <proj.h> |
---|
546 | #include <unistd.h> |
---|
547 | #include <sys/types.h> |
---|
548 | #endif |
---|
549 | |
---|
550 | #ifdef HAVE_TIS |
---|
551 | /* Support for TIS authentication server |
---|
552 | Contributed by Andre April <Andre.April@cediti.be>. */ |
---|
553 | #include "firewall.h" /* TIS authsrv authentication */ |
---|
554 | #endif |
---|
555 | |
---|
556 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
557 | #include <login_cap.h> |
---|
558 | #endif |
---|
559 | |
---|
560 | #ifdef _PATH_BSHELL |
---|
561 | #define DEFAULT_SHELL _PATH_BSHELL |
---|
562 | #else |
---|
563 | #define DEFAULT_SHELL "/bin/sh" |
---|
564 | #endif |
---|
565 | |
---|
566 | #ifndef DEFAULT_PATH |
---|
567 | #define DEFAULT_PATH "/bin/athena:/usr/athena/bin:/usr/bsd:/bin:/usr/bin:/usr/ucb:/usr/bin/X11:/usr/local/bin" |
---|
568 | #endif /* DEFAULT_PATH */ |
---|
569 | |
---|
570 | #ifndef O_NOCTTY |
---|
571 | #define O_NOCTTY 0 |
---|
572 | #endif |
---|
573 | |
---|
574 | #ifdef KERBEROS |
---|
575 | #ifdef KRB5 |
---|
576 | #include <krb5.h> |
---|
577 | /* Global the contexts */ |
---|
578 | krb5_context ssh_context = 0; |
---|
579 | krb5_auth_context auth_context = 0; |
---|
580 | int havecred = 0; |
---|
581 | #endif /* KRB5 */ |
---|
582 | char *ticket = "none\0"; |
---|
583 | #endif /* KERBEROS */ |
---|
584 | |
---|
585 | #include <al.h> |
---|
586 | extern int setpag(), ktc_ForgetAllTokens(); |
---|
587 | extern char *tkt_string(); |
---|
588 | void try_afscall(int (*func)(void)); |
---|
589 | void al_cleanup(void); |
---|
590 | int *al_warnings = NULL; |
---|
591 | char *al_user; |
---|
592 | int al_local_acct; |
---|
593 | |
---|
594 | /* Server configuration options. */ |
---|
595 | ServerOptions options; |
---|
596 | |
---|
597 | /* Name of the server configuration file. */ |
---|
598 | char *config_file_name = SERVER_CONFIG_FILE; |
---|
599 | |
---|
600 | /* Debug mode flag. This can be set on the command line. If debug |
---|
601 | mode is enabled, extra debugging output will be sent to the system |
---|
602 | log, the daemon will not go to background, and will exit after processing |
---|
603 | the first connection. */ |
---|
604 | int debug_flag = 0; |
---|
605 | |
---|
606 | /* Flag indicating that the daemon is being started from inetd. */ |
---|
607 | int inetd_flag = 0; |
---|
608 | |
---|
609 | /* argv[0] without path. */ |
---|
610 | char *av0; |
---|
611 | |
---|
612 | /* Saved arguments to main(). */ |
---|
613 | char **saved_argv; |
---|
614 | |
---|
615 | /* This is set to the socket that the server is listening; this is used in |
---|
616 | the SIGHUP signal handler. */ |
---|
617 | int listen_sock; |
---|
618 | |
---|
619 | /* Whether the server should accept connections. */ |
---|
620 | static int switched = 0; |
---|
621 | static int enabled = 1; |
---|
622 | |
---|
623 | /* This is not really needed, and could be eliminated if server-specific |
---|
624 | and client-specific code were removed from newchannels.c */ |
---|
625 | uid_t original_real_uid = 0; |
---|
626 | |
---|
627 | /* Flags set in auth-rsa from authorized_keys flags. These are set in |
---|
628 | auth-rsa.c. */ |
---|
629 | int no_port_forwarding_flag = 0; |
---|
630 | int no_agent_forwarding_flag = 0; |
---|
631 | int no_x11_forwarding_flag = 0; |
---|
632 | int no_pty_flag = 0; |
---|
633 | time_t idle_timeout = 0; |
---|
634 | char *forced_command = NULL; /* RSA authentication "command=" option. */ |
---|
635 | char *original_command = NULL; /* original command from protocol. */ |
---|
636 | struct envstring *custom_environment = NULL; |
---|
637 | /* RSA authentication "environment=" options. */ |
---|
638 | |
---|
639 | /* Session id for the current session. */ |
---|
640 | unsigned char session_id[16]; |
---|
641 | |
---|
642 | /* Any really sensitive data in the application is contained in this structure. |
---|
643 | The idea is that this structure could be locked into memory so that the |
---|
644 | pages do not get written into swap. However, there are some problems. |
---|
645 | The private key contains MP_INTs, and we do not (in principle) have |
---|
646 | access to the internals of them, and locking just the structure is not |
---|
647 | very useful. Currently, memory locking is not implemented. */ |
---|
648 | struct |
---|
649 | { |
---|
650 | /* Random number generator. */ |
---|
651 | RandomState random_state; |
---|
652 | |
---|
653 | /* Private part of server key. */ |
---|
654 | RSAPrivateKey private_key; |
---|
655 | |
---|
656 | /* Private part of host key. */ |
---|
657 | RSAPrivateKey host_key; |
---|
658 | } sensitive_data; |
---|
659 | |
---|
660 | /* Flag indicating whether the current session key has been used. This flag |
---|
661 | is set whenever the key is used, and cleared when the key is regenerated. */ |
---|
662 | int key_used = 0; |
---|
663 | |
---|
664 | /* This is set to true when SIGHUP is received. */ |
---|
665 | int received_sighup = 0; |
---|
666 | |
---|
667 | /* Public side of the server key. This value is regenerated regularly with |
---|
668 | the private key. */ |
---|
669 | RSAPublicKey public_key; |
---|
670 | |
---|
671 | /* Remote end username (mallocated) or NULL if not available */ |
---|
672 | char *remote_user_name; |
---|
673 | |
---|
674 | /* Days before the password / account expires, or -1 if information not |
---|
675 | available */ |
---|
676 | int days_before_account_expires = -1; |
---|
677 | int days_before_password_expires = -1; |
---|
678 | |
---|
679 | /* Prototypes for various functions defined later in this file. */ |
---|
680 | void do_connection(int privileged_port); |
---|
681 | void do_authentication(char *user, int privileged_port, int cipher_type); |
---|
682 | void do_authenticated(struct passwd *pw); |
---|
683 | void do_exec_pty(const char *command, int ptyfd, int ttyfd, |
---|
684 | const char *ttyname, struct passwd *pw, const char *term, |
---|
685 | const char *display, const char *auth_proto, |
---|
686 | const char *auth_data); |
---|
687 | void do_exec_no_pty(const char *command, struct passwd *pw, |
---|
688 | const char *display, const char *auth_proto, |
---|
689 | const char *auth_data); |
---|
690 | void do_child(const char *command, struct passwd *pw, const char *term, |
---|
691 | const char *display, const char *auth_proto, |
---|
692 | const char *auth_data, const char *ttyname); |
---|
693 | |
---|
694 | |
---|
695 | /* Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; |
---|
696 | the effect is to reread the configuration file (and to regenerate |
---|
697 | the server key). */ |
---|
698 | |
---|
699 | RETSIGTYPE sighup_handler(int sig) |
---|
700 | { |
---|
701 | received_sighup = 1; |
---|
702 | signal(SIGHUP, sighup_handler); |
---|
703 | } |
---|
704 | |
---|
705 | /* Called from the main program after receiving SIGHUP. Restarts the |
---|
706 | server. */ |
---|
707 | |
---|
708 | void sighup_restart(void) |
---|
709 | { |
---|
710 | log_msg("Received SIGHUP; restarting."); |
---|
711 | close(listen_sock); |
---|
712 | execvp(saved_argv[0], saved_argv); |
---|
713 | log_msg("RESTART FAILED: av[0]='%s', error: %s.", |
---|
714 | saved_argv[0], strerror(errno)); |
---|
715 | exit(1); |
---|
716 | } |
---|
717 | |
---|
718 | /* Generic signal handler for terminating signals in the master daemon. |
---|
719 | These close the listen socket; not closing it seems to cause "Address |
---|
720 | already in use" problems on some machines, which is inconvenient. */ |
---|
721 | |
---|
722 | RETSIGTYPE sigterm_handler(int sig) |
---|
723 | { |
---|
724 | log_msg("Received signal %d; terminating.", sig); |
---|
725 | close(listen_sock); |
---|
726 | exit(255); |
---|
727 | } |
---|
728 | |
---|
729 | #ifdef SIGDANGER |
---|
730 | /* Signal handler for AIX's SIGDANGER low-memory signal |
---|
731 | It logs the signal and ignores the message. */ |
---|
732 | RETSIGTYPE sigdanger_handler(int sig) |
---|
733 | { |
---|
734 | log_msg("Received signal %d (SIGDANGER, means memory is low); ignoring.", |
---|
735 | sig); |
---|
736 | } |
---|
737 | #endif /* SIGDANGER */ |
---|
738 | |
---|
739 | /* SIGCHLD handler. This is called whenever a child dies. This will then |
---|
740 | reap any zombies left by exited c. */ |
---|
741 | |
---|
742 | RETSIGTYPE main_sigchld_handler(int sig) |
---|
743 | { |
---|
744 | int status; |
---|
745 | #ifdef HAVE_WAITPID |
---|
746 | /* Reap all childrens */ |
---|
747 | while (waitpid(-1, &status, WNOHANG) > 0) |
---|
748 | ; |
---|
749 | #else |
---|
750 | wait(&status); |
---|
751 | #endif |
---|
752 | signal(SIGCHLD, main_sigchld_handler); |
---|
753 | } |
---|
754 | |
---|
755 | /* Signal handler for the alarm after the login grace period has expired. */ |
---|
756 | |
---|
757 | RETSIGTYPE grace_alarm_handler(int sig) |
---|
758 | { |
---|
759 | /* Close the connection. */ |
---|
760 | packet_close(); |
---|
761 | |
---|
762 | /* Log error and exit. */ |
---|
763 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
764 | "Timeout before authentication."); |
---|
765 | } |
---|
766 | |
---|
767 | /* Signal handler for the key regeneration alarm. Note that this |
---|
768 | alarm only occurs in the daemon waiting for connections, and it does not |
---|
769 | do anything with the private key or random state before forking. Thus there |
---|
770 | should be no concurrency control/asynchronous execution problems. */ |
---|
771 | |
---|
772 | RETSIGTYPE key_regeneration_alarm(int sig) |
---|
773 | { |
---|
774 | /* Check if we should generate a new key. */ |
---|
775 | if (key_used) |
---|
776 | { |
---|
777 | /* This should really be done in the background. */ |
---|
778 | log_msg("Generating new %d bit RSA key.", options.server_key_bits); |
---|
779 | random_acquire_light_environmental_noise(&sensitive_data.random_state); |
---|
780 | rsa_generate_key(&sensitive_data.private_key, &public_key, |
---|
781 | &sensitive_data.random_state, options.server_key_bits); |
---|
782 | random_save(&sensitive_data.random_state, geteuid(), |
---|
783 | options.random_seed_file); |
---|
784 | key_used = 0; |
---|
785 | log_msg("RSA key generation complete."); |
---|
786 | } |
---|
787 | |
---|
788 | /* Reschedule the alarm. */ |
---|
789 | signal(SIGALRM, key_regeneration_alarm); |
---|
790 | alarm(options.key_regeneration_time); |
---|
791 | } |
---|
792 | |
---|
793 | RETSIGTYPE sigusr1_handler(int sig) |
---|
794 | { |
---|
795 | enabled = 1; |
---|
796 | signal(SIGUSR1, sigusr1_handler); |
---|
797 | } |
---|
798 | |
---|
799 | RETSIGTYPE sigusr2_handler(int sig) |
---|
800 | { |
---|
801 | if (switched) |
---|
802 | enabled = 0; |
---|
803 | signal(SIGUSR2, sigusr2_handler); |
---|
804 | } |
---|
805 | |
---|
806 | /* Main program for the daemon. */ |
---|
807 | |
---|
808 | int main(int ac, char **av) |
---|
809 | { |
---|
810 | extern char *optarg; |
---|
811 | extern int optind; |
---|
812 | int opt, aux, sock_in, sock_out, newsock, i, pid, on = 1; |
---|
813 | int remote_major, remote_minor; |
---|
814 | int perm_denied = 0; |
---|
815 | int ret; |
---|
816 | fd_set fdset; |
---|
817 | struct sockaddr_in sin; |
---|
818 | char buf[100]; /* Must not be larger than remote_version. */ |
---|
819 | char remote_version[100]; /* Must be at least as big as buf. */ |
---|
820 | char *comment; |
---|
821 | char *ssh_remote_version_string = NULL; |
---|
822 | FILE *f; |
---|
823 | #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER) |
---|
824 | struct linger linger; |
---|
825 | #endif /* SO_LINGER */ |
---|
826 | int done; |
---|
827 | |
---|
828 | /* Save argv[0]. */ |
---|
829 | saved_argv = av; |
---|
830 | if (strchr(av[0], '/')) |
---|
831 | av0 = strrchr(av[0], '/') + 1; |
---|
832 | else |
---|
833 | av0 = av[0]; |
---|
834 | |
---|
835 | /* Prevent core dumps to avoid revealing sensitive information. */ |
---|
836 | signals_prevent_core(); |
---|
837 | |
---|
838 | /* Set SIGPIPE to be ignored. */ |
---|
839 | signal(SIGPIPE, SIG_IGN); |
---|
840 | |
---|
841 | /* Initialize configuration options to their default values. */ |
---|
842 | initialize_server_options(&options); |
---|
843 | |
---|
844 | /* Parse command-line arguments. */ |
---|
845 | while ((opt = getopt(ac, av, "f:p:b:k:h:g:diqV:sS")) != EOF) |
---|
846 | { |
---|
847 | switch (opt) |
---|
848 | { |
---|
849 | case 'f': |
---|
850 | config_file_name = optarg; |
---|
851 | break; |
---|
852 | case 'd': |
---|
853 | debug_flag = 1; |
---|
854 | break; |
---|
855 | case 'i': |
---|
856 | inetd_flag = 1; |
---|
857 | break; |
---|
858 | case 'q': |
---|
859 | options.quiet_mode = 1; |
---|
860 | break; |
---|
861 | case 'b': |
---|
862 | options.server_key_bits = atoi(optarg); |
---|
863 | break; |
---|
864 | case 'p': |
---|
865 | options.port = atoi(optarg); |
---|
866 | break; |
---|
867 | case 'g': |
---|
868 | options.login_grace_time = atoi(optarg); |
---|
869 | break; |
---|
870 | case 'k': |
---|
871 | options.key_regeneration_time = atoi(optarg); |
---|
872 | break; |
---|
873 | case 'h': |
---|
874 | options.host_key_file = optarg; |
---|
875 | break; |
---|
876 | case 's': |
---|
877 | switched = 1; |
---|
878 | break; |
---|
879 | case 'S': |
---|
880 | switched = 1; |
---|
881 | enabled = 0; |
---|
882 | break; |
---|
883 | case 'V': |
---|
884 | ssh_remote_version_string = optarg; |
---|
885 | break; |
---|
886 | case '?': |
---|
887 | default: |
---|
888 | #ifdef F_SECURE_COMMERCIAL |
---|
889 | |
---|
890 | #endif /* F_SECURE_COMMERCIAL */ |
---|
891 | fprintf(stderr, "sshd version %s [%s]\n", SSH_VERSION, HOSTTYPE); |
---|
892 | fprintf(stderr, "Usage: %s [options]\n", av0); |
---|
893 | fprintf(stderr, "Options:\n"); |
---|
894 | fprintf(stderr, " -f file Configuration file (default %s/sshd_config)\n", ETCDIR); |
---|
895 | fprintf(stderr, " -d Debugging mode\n"); |
---|
896 | fprintf(stderr, " -i Started from inetd\n"); |
---|
897 | fprintf(stderr, " -q Quiet (no logging)\n"); |
---|
898 | fprintf(stderr, " -p port Listen on the specified port (default: 22)\n"); |
---|
899 | fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n"); |
---|
900 | fprintf(stderr, " -g seconds Grace period for authentication (default: 300)\n"); |
---|
901 | fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); |
---|
902 | fprintf(stderr, " -h file File from which to read host key (default: %s)\n", |
---|
903 | HOST_KEY_FILE); |
---|
904 | fprintf(stderr, " -V str Remote version string already read from the socket\n"); |
---|
905 | exit(1); |
---|
906 | } |
---|
907 | } |
---|
908 | |
---|
909 | /* Read server configuration options from the configuration file. */ |
---|
910 | read_server_config(&options, config_file_name); |
---|
911 | |
---|
912 | /* Fill in default values for those options not explicitly set. */ |
---|
913 | fill_default_server_options(&options); |
---|
914 | |
---|
915 | /* Check certain values for sanity. */ |
---|
916 | if (options.server_key_bits < 512 || |
---|
917 | options.server_key_bits > 32768) |
---|
918 | { |
---|
919 | fprintf(stderr, "fatal: Bad server key size.\n"); |
---|
920 | exit(1); |
---|
921 | } |
---|
922 | if (options.port < 1 || options.port > 65535) |
---|
923 | { |
---|
924 | fprintf(stderr, "fatal: Bad port number.\n"); |
---|
925 | exit(1); |
---|
926 | } |
---|
927 | if (options.umask != -1) |
---|
928 | { |
---|
929 | umask(options.umask); |
---|
930 | } |
---|
931 | |
---|
932 | /* Check that there are no remaining arguments. */ |
---|
933 | if (optind < ac) |
---|
934 | { |
---|
935 | fprintf(stderr, "fatal: Extra argument %s.\n", av[optind]); |
---|
936 | exit(1); |
---|
937 | } |
---|
938 | |
---|
939 | /* Initialize the log (it is reinitialized below in case we forked). */ |
---|
940 | log_init(av0, debug_flag && !inetd_flag, |
---|
941 | debug_flag || options.fascist_logging, |
---|
942 | options.quiet_mode, options.log_facility); |
---|
943 | |
---|
944 | #ifdef F_SECURE_COMMERCIAL |
---|
945 | |
---|
946 | #endif /* F_SECURE_COMMERCIAL */ |
---|
947 | debug("sshd version %.100s [%.100s]", SSH_VERSION, HOSTTYPE); |
---|
948 | |
---|
949 | /* Load the host key. It must have empty passphrase. */ |
---|
950 | done = load_private_key(geteuid(), options.host_key_file, "", |
---|
951 | &sensitive_data.host_key, &comment); |
---|
952 | |
---|
953 | #ifdef SECURE_RPC |
---|
954 | if (!done) |
---|
955 | { |
---|
956 | char *passphrase; |
---|
957 | |
---|
958 | passphrase = userfile_get_des_1_magic_phrase(geteuid()); |
---|
959 | if (passphrase != NULL) |
---|
960 | { |
---|
961 | done = load_private_key(geteuid(), options.host_key_file, |
---|
962 | passphrase, &sensitive_data.host_key, &comment); |
---|
963 | if (done) |
---|
964 | debug ("Using SUN-DES-1 magic phrase to decrypt host key."); |
---|
965 | memset(passphrase, 0, strlen(passphrase)); |
---|
966 | xfree(passphrase); |
---|
967 | } |
---|
968 | } |
---|
969 | #endif |
---|
970 | if (!done) |
---|
971 | { |
---|
972 | if (debug_flag) |
---|
973 | { |
---|
974 | fprintf(stderr, "Could not load host key: %.200s\n", |
---|
975 | options.host_key_file); |
---|
976 | fprintf(stderr, "fatal: Please check that you have sufficient permissions and the file exists.\n"); |
---|
977 | } |
---|
978 | else |
---|
979 | { |
---|
980 | log_init(av0, !inetd_flag, 1, 0, options.log_facility); |
---|
981 | error("fatal: Could not load host key: %.200s. Check path and permissions.", |
---|
982 | options.host_key_file); |
---|
983 | } |
---|
984 | exit(1); |
---|
985 | } |
---|
986 | xfree(comment); |
---|
987 | |
---|
988 | #ifdef SCO |
---|
989 | (void) set_auth_parameters(ac, av); |
---|
990 | #endif |
---|
991 | |
---|
992 | #ifdef HAVE_OSF1_C2_SECURITY |
---|
993 | initialize_osf_security(ac, av); |
---|
994 | #endif /* HAVE_OSF1_C2_SECURITY */ |
---|
995 | |
---|
996 | /* If not in debugging mode, and not started from inetd, disconnect from |
---|
997 | the controlling terminal, and fork. The original process exits. */ |
---|
998 | if (!debug_flag && !inetd_flag) |
---|
999 | #ifdef HAVE_DAEMON |
---|
1000 | if (daemon(0, 0) < 0) |
---|
1001 | error("daemon: %.100s", strerror(errno)); |
---|
1002 | #else /* HAVE_DAEMON */ |
---|
1003 | { |
---|
1004 | #ifdef TIOCNOTTY |
---|
1005 | int fd; |
---|
1006 | #endif /* TIOCNOTTY */ |
---|
1007 | |
---|
1008 | /* Fork, and have the parent exit. The child becomes the server. */ |
---|
1009 | if (fork()) |
---|
1010 | exit(0); |
---|
1011 | |
---|
1012 | /* Redirect stdin, stdout, and stderr to /dev/null. */ |
---|
1013 | freopen("/dev/null", "r", stdin); |
---|
1014 | freopen("/dev/null", "w", stdout); |
---|
1015 | freopen("/dev/null", "w", stderr); |
---|
1016 | |
---|
1017 | /* Disconnect from the controlling tty. */ |
---|
1018 | #ifdef TIOCNOTTY |
---|
1019 | fd = open("/dev/tty", O_RDWR|O_NOCTTY); |
---|
1020 | if (fd >= 0) |
---|
1021 | { |
---|
1022 | (void)ioctl(fd, TIOCNOTTY, NULL); |
---|
1023 | close(fd); |
---|
1024 | } |
---|
1025 | #endif /* TIOCNOTTY */ |
---|
1026 | #ifdef HAVE_SETSID |
---|
1027 | #ifdef ultrix |
---|
1028 | setpgrp(0, 0); |
---|
1029 | #else /* ultrix */ |
---|
1030 | if (setsid() < 0) |
---|
1031 | error("setsid: %.100s", strerror(errno)); |
---|
1032 | #endif |
---|
1033 | #endif /* HAVE_SETSID */ |
---|
1034 | } |
---|
1035 | #endif /* HAVE_DAEMON */ |
---|
1036 | |
---|
1037 | /* Reinitialize the log (because of the fork above). */ |
---|
1038 | log_init(av0, debug_flag && !inetd_flag, |
---|
1039 | debug_flag || options.fascist_logging, |
---|
1040 | options.quiet_mode, options.log_facility); |
---|
1041 | |
---|
1042 | /* Check that server and host key lengths differ sufficiently. This is |
---|
1043 | necessary to make double encryption work with rsaref. Oh, I hate |
---|
1044 | software patents. */ |
---|
1045 | if (options.server_key_bits > |
---|
1046 | sensitive_data.host_key.bits - SSH_KEY_BITS_RESERVED && |
---|
1047 | options.server_key_bits < |
---|
1048 | sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED) |
---|
1049 | { |
---|
1050 | options.server_key_bits = |
---|
1051 | sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED; |
---|
1052 | debug("Forcing server key to %d bits to make it differ from host key.", |
---|
1053 | options.server_key_bits); |
---|
1054 | } |
---|
1055 | |
---|
1056 | /* Initialize memory allocation so that any freed MP_INT data will be |
---|
1057 | zeroed. */ |
---|
1058 | rsa_set_mp_memory_allocation(); |
---|
1059 | |
---|
1060 | /* Do not display messages to stdout in RSA code. */ |
---|
1061 | rsa_set_verbose(debug_flag); |
---|
1062 | |
---|
1063 | /* Initialize the random number generator. */ |
---|
1064 | debug("Initializing random number generator; seed file %.200s", |
---|
1065 | options.random_seed_file); |
---|
1066 | random_initialize(&sensitive_data.random_state, geteuid(), |
---|
1067 | options.random_seed_file); |
---|
1068 | |
---|
1069 | /* Chdir to the root directory so that the current disk can be unmounted |
---|
1070 | if desired. */ |
---|
1071 | chdir("/"); |
---|
1072 | |
---|
1073 | idle_timeout = options.idle_timeout; |
---|
1074 | |
---|
1075 | /* Start listening for a socket, unless started from inetd. */ |
---|
1076 | if (inetd_flag) |
---|
1077 | { |
---|
1078 | int s1, s2; |
---|
1079 | s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */ |
---|
1080 | s2 = dup(s1); |
---|
1081 | sock_in = dup(0); |
---|
1082 | sock_out = dup(1); |
---|
1083 | /* We intentionally do not close the descriptors 0, 1, and 2 as our |
---|
1084 | code for setting the descriptors won\'t work if ttyfd happens to |
---|
1085 | be one of those. */ |
---|
1086 | debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); |
---|
1087 | |
---|
1088 | /* Generate an rsa key. */ |
---|
1089 | log_msg("Generating %d bit RSA key.", options.server_key_bits); |
---|
1090 | rsa_generate_key(&sensitive_data.private_key, &public_key, |
---|
1091 | &sensitive_data.random_state, |
---|
1092 | options.server_key_bits); |
---|
1093 | random_save(&sensitive_data.random_state, geteuid(), |
---|
1094 | options.random_seed_file); |
---|
1095 | log_msg("RSA key generation complete."); |
---|
1096 | } |
---|
1097 | else |
---|
1098 | { |
---|
1099 | /* Create socket for listening. */ |
---|
1100 | listen_sock = socket(AF_INET, SOCK_STREAM, 0); |
---|
1101 | if (listen_sock < 0) |
---|
1102 | fatal("socket: %.100s", strerror(errno)); |
---|
1103 | |
---|
1104 | /* Set socket options. We try to make the port reusable and have it |
---|
1105 | close as fast as possible without waiting in unnecessary wait states |
---|
1106 | on close. */ |
---|
1107 | setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, |
---|
1108 | sizeof(on)); |
---|
1109 | #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER) |
---|
1110 | linger.l_onoff = 1; |
---|
1111 | linger.l_linger = 15; |
---|
1112 | setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *)&linger, |
---|
1113 | sizeof(linger)); |
---|
1114 | #endif /* SO_LINGER */ |
---|
1115 | |
---|
1116 | /* Initialize the socket address. */ |
---|
1117 | memset(&sin, 0, sizeof(sin)); |
---|
1118 | sin.sin_family = AF_INET; |
---|
1119 | sin.sin_addr = options.listen_addr; |
---|
1120 | sin.sin_port = htons(options.port); |
---|
1121 | |
---|
1122 | /* Bind the socket to the desired port. */ |
---|
1123 | if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) |
---|
1124 | { |
---|
1125 | error("bind: %.100s", strerror(errno)); |
---|
1126 | shutdown(listen_sock, 2); |
---|
1127 | close(listen_sock); |
---|
1128 | fatal("Bind to port %d failed: %.200s.", options.port, |
---|
1129 | strerror(errno)); |
---|
1130 | } |
---|
1131 | |
---|
1132 | if (!debug_flag) |
---|
1133 | { |
---|
1134 | /* Record our pid in /etc/sshd_pid to make it easier to kill the |
---|
1135 | correct sshd. We don\'t want to do this before the bind above |
---|
1136 | because the bind will fail if there already is a daemon, and this |
---|
1137 | will overwrite any old pid in the file. */ |
---|
1138 | f = fopen(options.pid_file, "w"); |
---|
1139 | if (f) |
---|
1140 | { |
---|
1141 | fprintf(f, "%u\n", (unsigned int)getpid()); |
---|
1142 | fclose(f); |
---|
1143 | } |
---|
1144 | } |
---|
1145 | |
---|
1146 | /* Start listening on the port. */ |
---|
1147 | log_msg("Server listening on port %d.", options.port); |
---|
1148 | if (listen(listen_sock, 5) < 0) |
---|
1149 | fatal("listen: %.100s", strerror(errno)); |
---|
1150 | |
---|
1151 | /* Generate an rsa key. */ |
---|
1152 | log_msg("Generating %d bit RSA key.", options.server_key_bits); |
---|
1153 | rsa_generate_key(&sensitive_data.private_key, &public_key, |
---|
1154 | &sensitive_data.random_state, |
---|
1155 | options.server_key_bits); |
---|
1156 | random_save(&sensitive_data.random_state, geteuid(), |
---|
1157 | options.random_seed_file); |
---|
1158 | log_msg("RSA key generation complete."); |
---|
1159 | |
---|
1160 | /* Schedule server key regeneration alarm. */ |
---|
1161 | signal(SIGALRM, key_regeneration_alarm); |
---|
1162 | alarm(options.key_regeneration_time); |
---|
1163 | |
---|
1164 | /* Arrange to restart on SIGHUP. The handler needs listen_sock. */ |
---|
1165 | signal(SIGHUP, sighup_handler); |
---|
1166 | signal(SIGTERM, sigterm_handler); |
---|
1167 | signal(SIGQUIT, sigterm_handler); |
---|
1168 | |
---|
1169 | /* Switch on and off on SIGUSR1 and SIGUSR2 (conditional on switched). */ |
---|
1170 | signal(SIGUSR1, sigusr1_handler); |
---|
1171 | signal(SIGUSR2, sigusr2_handler); |
---|
1172 | |
---|
1173 | /* AIX sends SIGDANGER when memory runs low. The default action is |
---|
1174 | to terminate the process. This sometimes makes it difficult to |
---|
1175 | log in and fix the problem. */ |
---|
1176 | |
---|
1177 | #ifdef SIGDANGER |
---|
1178 | signal(SIGDANGER, sigdanger_handler); |
---|
1179 | #endif /* SIGDANGER */ |
---|
1180 | |
---|
1181 | /* Arrange SIGCHLD to be caught. */ |
---|
1182 | signal(SIGCHLD, main_sigchld_handler); |
---|
1183 | |
---|
1184 | #ifdef KERBEROS |
---|
1185 | #ifdef KRB5 |
---|
1186 | /* Initialize contexts and setup replay cache */ |
---|
1187 | if (!ssh_context) |
---|
1188 | { |
---|
1189 | krb5_error_code r; |
---|
1190 | |
---|
1191 | if ((r = krb5_init_context(&ssh_context))) |
---|
1192 | fatal("Kerberos V5: %s while initializing krb5.", |
---|
1193 | error_message(r)); |
---|
1194 | krb5_init_ets(ssh_context); |
---|
1195 | } |
---|
1196 | #endif |
---|
1197 | #endif |
---|
1198 | |
---|
1199 | /* Stay listening for connections until the system crashes or the |
---|
1200 | daemon is killed with a signal. */ |
---|
1201 | for (;;) |
---|
1202 | { |
---|
1203 | if (received_sighup) |
---|
1204 | sighup_restart(); |
---|
1205 | |
---|
1206 | /* Wait in select until there is a connection. */ |
---|
1207 | FD_ZERO(&fdset); |
---|
1208 | FD_SET(listen_sock, &fdset); |
---|
1209 | ret = select(listen_sock + 1, &fdset, NULL, NULL, NULL); |
---|
1210 | if (ret < 0 || !FD_ISSET(listen_sock, &fdset)) |
---|
1211 | { |
---|
1212 | if (errno == EINTR) |
---|
1213 | continue; |
---|
1214 | error("select: %.100s", strerror(errno)); |
---|
1215 | continue; |
---|
1216 | } |
---|
1217 | |
---|
1218 | aux = sizeof(sin); |
---|
1219 | newsock = accept(listen_sock, (struct sockaddr *)&sin, &aux); |
---|
1220 | if (newsock < 0) |
---|
1221 | { |
---|
1222 | if (errno == EINTR) |
---|
1223 | continue; |
---|
1224 | error("accept: %.100s", strerror(errno)); |
---|
1225 | continue; |
---|
1226 | } |
---|
1227 | |
---|
1228 | /* Got connection. Fork a child to handle it, unless we are in |
---|
1229 | debugging mode. */ |
---|
1230 | if (debug_flag) |
---|
1231 | { |
---|
1232 | /* In debugging mode. Close the listening socket, and start |
---|
1233 | processing the connection without forking. */ |
---|
1234 | debug("Server will not fork when running in debugging mode."); |
---|
1235 | close(listen_sock); |
---|
1236 | sock_in = newsock; |
---|
1237 | sock_out = newsock; |
---|
1238 | pid = getpid(); |
---|
1239 | #ifdef LIBWRAP |
---|
1240 | { |
---|
1241 | struct request_info req; |
---|
1242 | |
---|
1243 | signal(SIGCHLD, SIG_DFL); |
---|
1244 | |
---|
1245 | request_init(&req, RQ_DAEMON, av0, RQ_FILE, newsock, NULL); |
---|
1246 | fromhost(&req); |
---|
1247 | if (!hosts_access(&req) || !enabled) |
---|
1248 | refuse(&req); |
---|
1249 | } |
---|
1250 | #endif /* LIBWRAP */ |
---|
1251 | break; |
---|
1252 | } |
---|
1253 | else |
---|
1254 | { |
---|
1255 | /* Normal production daemon. Fork, and have the child process |
---|
1256 | the connection. The parent continues listening. */ |
---|
1257 | if ((pid = fork()) == 0) |
---|
1258 | { |
---|
1259 | /* Child. Close the listening socket, and start using |
---|
1260 | the accepted socket. Reinitialize logging (since our |
---|
1261 | pid has changed). We break out of the loop to handle |
---|
1262 | the connection. */ |
---|
1263 | close(listen_sock); |
---|
1264 | sock_in = newsock; |
---|
1265 | sock_out = newsock; |
---|
1266 | #ifdef LIBWRAP |
---|
1267 | { |
---|
1268 | struct request_info req; |
---|
1269 | |
---|
1270 | signal(SIGCHLD, SIG_DFL); |
---|
1271 | |
---|
1272 | request_init(&req, RQ_DAEMON, av0, RQ_FILE, newsock, NULL); |
---|
1273 | fromhost(&req); |
---|
1274 | if (!hosts_access(&req) || !enabled) |
---|
1275 | refuse(&req); |
---|
1276 | } |
---|
1277 | #endif /* LIBWRAP */ |
---|
1278 | |
---|
1279 | log_init(av0, debug_flag && !inetd_flag, |
---|
1280 | options.fascist_logging || debug_flag, |
---|
1281 | options.quiet_mode, options.log_facility); |
---|
1282 | break; |
---|
1283 | } |
---|
1284 | } |
---|
1285 | |
---|
1286 | /* Parent. Stay in the loop. */ |
---|
1287 | if (pid < 0) |
---|
1288 | error("fork: %.100s", strerror(errno)); |
---|
1289 | else |
---|
1290 | debug("Forked child %d.", pid); |
---|
1291 | |
---|
1292 | /* Mark that the key has been used (it was "given" to the child). */ |
---|
1293 | key_used = 1; |
---|
1294 | |
---|
1295 | random_acquire_light_environmental_noise(&sensitive_data. |
---|
1296 | random_state); |
---|
1297 | |
---|
1298 | /* Close the new socket (the child is now taking care of it). */ |
---|
1299 | close(newsock); |
---|
1300 | } |
---|
1301 | } |
---|
1302 | |
---|
1303 | /* This is the child processing a new connection. */ |
---|
1304 | |
---|
1305 | /* Disable the key regeneration alarm. We will not regenerate the key |
---|
1306 | since we are no longer in a position to give it to anyone. We will |
---|
1307 | not restart on SIGHUP since it no longer makes sense. */ |
---|
1308 | alarm(0); |
---|
1309 | signal(SIGALRM, SIG_DFL); |
---|
1310 | signal(SIGHUP, SIG_DFL); |
---|
1311 | signal(SIGTERM, SIG_DFL); |
---|
1312 | signal(SIGQUIT, SIG_DFL); |
---|
1313 | signal(SIGCHLD, SIG_DFL); |
---|
1314 | |
---|
1315 | /* Set socket options for the connection. We want the socket to close |
---|
1316 | as fast as possible without waiting for anything. If the connection |
---|
1317 | is not a socket, these will do nothing. */ |
---|
1318 | /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ |
---|
1319 | #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER) |
---|
1320 | linger.l_onoff = 1; |
---|
1321 | linger.l_linger = 15; |
---|
1322 | setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)); |
---|
1323 | #endif /* SO_LINGER */ |
---|
1324 | |
---|
1325 | /* Register our connection. This turns encryption off because we do not |
---|
1326 | have a key. */ |
---|
1327 | packet_set_connection(sock_in, sock_out, &sensitive_data.random_state); |
---|
1328 | |
---|
1329 | /* Log the connection. */ |
---|
1330 | log_msg("Connection from %.100s port %d", |
---|
1331 | get_remote_ipaddr(), get_remote_port()); |
---|
1332 | |
---|
1333 | /* Check whether logins are denied from this host. */ |
---|
1334 | { |
---|
1335 | const char *hostname = get_canonical_hostname(); |
---|
1336 | const char *ipaddr = get_remote_ipaddr(); |
---|
1337 | int i; |
---|
1338 | if (options.num_deny_hosts > 0) |
---|
1339 | { |
---|
1340 | for (i = 0; i < options.num_deny_hosts; i++) |
---|
1341 | if (match_host(hostname, ipaddr, options.deny_hosts[i])) |
---|
1342 | perm_denied = 1; |
---|
1343 | } |
---|
1344 | if ((!perm_denied) && options.num_allow_hosts > 0) |
---|
1345 | { |
---|
1346 | for (i = 0; i < options.num_allow_hosts; i++) |
---|
1347 | if (match_host(hostname, ipaddr, options.allow_hosts[i])) |
---|
1348 | break; |
---|
1349 | if (i >= options.num_allow_hosts) |
---|
1350 | perm_denied = 1; |
---|
1351 | } |
---|
1352 | if (perm_denied && options.silent_deny) |
---|
1353 | { |
---|
1354 | close(sock_in); |
---|
1355 | close(sock_out); |
---|
1356 | exit(0); |
---|
1357 | } |
---|
1358 | } |
---|
1359 | |
---|
1360 | /* We don\'t want to listen forever unless the other side successfully |
---|
1361 | authenticates itself. So we set up an alarm which is cleared after |
---|
1362 | successful authentication. A limit of zero indicates no limit. |
---|
1363 | Note that we don\'t set the alarm in debugging mode; it is just annoying |
---|
1364 | to have the server exit just when you are about to discover the bug. */ |
---|
1365 | signal(SIGALRM, grace_alarm_handler); |
---|
1366 | if (!debug_flag) |
---|
1367 | alarm(options.login_grace_time); |
---|
1368 | |
---|
1369 | |
---|
1370 | if (ssh_remote_version_string == NULL) |
---|
1371 | { |
---|
1372 | /* Send our protocol version identification. */ |
---|
1373 | sprintf(buf, "SSH-%d.%d-%.50s", |
---|
1374 | PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); |
---|
1375 | #ifdef F_SECURE_COMMERCIAL |
---|
1376 | |
---|
1377 | #endif /* F_SECURE_COMMERCIAL */ |
---|
1378 | strcat(buf, "\n"); |
---|
1379 | if (write(sock_out, buf, strlen(buf)) != strlen(buf)) |
---|
1380 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
1381 | "Could not write ident string."); |
---|
1382 | } |
---|
1383 | |
---|
1384 | if (ssh_remote_version_string == NULL) |
---|
1385 | { |
---|
1386 | /* Read other side\'s version identification. */ |
---|
1387 | for (i = 0; i < sizeof(buf) - 1; i++) |
---|
1388 | { |
---|
1389 | if (read(sock_in, &buf[i], 1) != 1) |
---|
1390 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
1391 | "Did not receive ident string."); |
---|
1392 | if (buf[i] == '\r') |
---|
1393 | { |
---|
1394 | buf[i] = '\n'; |
---|
1395 | buf[i + 1] = 0; |
---|
1396 | break; |
---|
1397 | } |
---|
1398 | if (buf[i] == '\n') |
---|
1399 | { |
---|
1400 | /* buf[i] == '\n' */ |
---|
1401 | buf[i + 1] = 0; |
---|
1402 | break; |
---|
1403 | } |
---|
1404 | } |
---|
1405 | buf[sizeof(buf) - 1] = 0; |
---|
1406 | } |
---|
1407 | else |
---|
1408 | { |
---|
1409 | strncpy(buf, ssh_remote_version_string, sizeof(buf) - 1); |
---|
1410 | buf[sizeof(buf) - 1] = 0; |
---|
1411 | } |
---|
1412 | |
---|
1413 | /* Check that the versions match. In future this might accept several |
---|
1414 | versions and set appropriate flags to handle them. */ |
---|
1415 | if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, |
---|
1416 | remote_version) != 3) |
---|
1417 | { |
---|
1418 | const char *s = "Protocol mismatch.\n"; |
---|
1419 | (void) write(sock_out, s, strlen(s)); |
---|
1420 | close(sock_in); |
---|
1421 | close(sock_out); |
---|
1422 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
1423 | "Bad protocol version identification: %.100s", buf); |
---|
1424 | } |
---|
1425 | debug("Client protocol version %d.%d; client software version %.100s", |
---|
1426 | remote_major, remote_minor, remote_version); |
---|
1427 | |
---|
1428 | switch (check_emulation(remote_major, remote_minor, |
---|
1429 | NULL, NULL)) |
---|
1430 | { |
---|
1431 | case EMULATE_MAJOR_VERSION_MISMATCH: |
---|
1432 | { |
---|
1433 | const char *s = "Protocol major versions differ.\n"; |
---|
1434 | (void) write(sock_out, s, strlen(s)); |
---|
1435 | close(sock_in); |
---|
1436 | close(sock_out); |
---|
1437 | fatal_severity(SYSLOG_SEVERITY_INFO, |
---|
1438 | "Protocol major versions differ: %d vs. %d", |
---|
1439 | PROTOCOL_MAJOR, remote_major); |
---|
1440 | } |
---|
1441 | break; |
---|
1442 | case EMULATE_VERSION_TOO_OLD: |
---|
1443 | packet_disconnect("Your ssh version is too old and is no " |
---|
1444 | "longer supported. Please install a newer version."); |
---|
1445 | break; |
---|
1446 | case EMULATE_VERSION_NEWER: |
---|
1447 | packet_disconnect("This server does not support your " |
---|
1448 | "new ssh version."); |
---|
1449 | break; |
---|
1450 | case EMULATE_VERSION_OK: |
---|
1451 | break; |
---|
1452 | default: |
---|
1453 | fatal("Unexpected return value from check_emulation."); |
---|
1454 | } |
---|
1455 | |
---|
1456 | if (perm_denied) |
---|
1457 | { |
---|
1458 | const char *hostname = get_canonical_hostname(); |
---|
1459 | |
---|
1460 | log_msg("Connection from %.200s not allowed.\n", hostname); |
---|
1461 | packet_disconnect("Sorry, you are not allowed to connect."); |
---|
1462 | /*NOTREACHED*/ |
---|
1463 | } |
---|
1464 | |
---|
1465 | packet_set_nonblocking(); |
---|
1466 | |
---|
1467 | /* Handle the connection. We pass as argument whether the connection |
---|
1468 | came from a privileged port. */ |
---|
1469 | do_connection(get_remote_port() < 1024); |
---|
1470 | |
---|
1471 | /* Try to remove authentication socket and directory */ |
---|
1472 | auth_delete_socket(NULL); |
---|
1473 | |
---|
1474 | /* The connection has been terminated. */ |
---|
1475 | log_msg("Closing connection to %.100s", get_remote_ipaddr()); |
---|
1476 | packet_close(); |
---|
1477 | exit(0); |
---|
1478 | } |
---|
1479 | |
---|
1480 | /* Process an incoming connection. Protocol version identifiers have already |
---|
1481 | been exchanged. This sends server key and performs the key exchange. |
---|
1482 | Server and host keys will no longer be needed after this functions. */ |
---|
1483 | |
---|
1484 | void do_connection(int privileged_port) |
---|
1485 | { |
---|
1486 | int i; |
---|
1487 | MP_INT session_key_int; |
---|
1488 | unsigned char session_key[SSH_SESSION_KEY_LENGTH]; |
---|
1489 | unsigned char check_bytes[8]; |
---|
1490 | char *user; |
---|
1491 | unsigned int cipher_type, auth_mask, protocol_flags; |
---|
1492 | |
---|
1493 | /* Generate check bytes that the client must send back in the user packet |
---|
1494 | in order for it to be accepted; this is used to defy ip spoofing |
---|
1495 | attacks. Note that this only works against somebody doing IP spoofing |
---|
1496 | from a remote machine; any machine on the local network can still see |
---|
1497 | outgoing packets and catch the random cookie. This only affects |
---|
1498 | rhosts authentication, and this is one of the reasons why it is |
---|
1499 | inherently insecure. */ |
---|
1500 | for (i = 0; i < 8; i++) |
---|
1501 | check_bytes[i] = random_get_byte(&sensitive_data.random_state); |
---|
1502 | |
---|
1503 | /* Send our public key. We include in the packet 64 bits of random |
---|
1504 | data that must be matched in the reply in order to prevent IP spoofing. */ |
---|
1505 | packet_start(SSH_SMSG_PUBLIC_KEY); |
---|
1506 | for (i = 0; i < 8; i++) |
---|
1507 | packet_put_char(check_bytes[i]); |
---|
1508 | |
---|
1509 | /* Store our public server RSA key. */ |
---|
1510 | packet_put_int(public_key.bits); |
---|
1511 | packet_put_mp_int(&public_key.e); |
---|
1512 | packet_put_mp_int(&public_key.n); |
---|
1513 | |
---|
1514 | /* Store our public host RSA key. */ |
---|
1515 | packet_put_int(sensitive_data.host_key.bits); |
---|
1516 | packet_put_mp_int(&sensitive_data.host_key.e); |
---|
1517 | packet_put_mp_int(&sensitive_data.host_key.n); |
---|
1518 | |
---|
1519 | /* Put protocol flags. */ |
---|
1520 | packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); |
---|
1521 | |
---|
1522 | /* Declare which ciphers we support. */ |
---|
1523 | packet_put_int(cipher_mask()); |
---|
1524 | |
---|
1525 | /* Declare supported authentication types. */ |
---|
1526 | auth_mask = 0; |
---|
1527 | if (options.rhosts_authentication) |
---|
1528 | auth_mask |= 1 << SSH_AUTH_RHOSTS; |
---|
1529 | if (options.rhosts_rsa_authentication) |
---|
1530 | auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA; |
---|
1531 | if (options.rsa_authentication) |
---|
1532 | auth_mask |= 1 << SSH_AUTH_RSA; |
---|
1533 | #ifdef HAVE_TIS |
---|
1534 | if (options.tis_authentication) |
---|
1535 | auth_mask |= 1 << SSH_AUTH_TIS; |
---|
1536 | #endif |
---|
1537 | #ifdef KERBEROS |
---|
1538 | #ifdef KRB5 |
---|
1539 | if (options.kerberos_authentication) |
---|
1540 | auth_mask |= 1 << SSH_AUTH_KERBEROS; |
---|
1541 | #endif |
---|
1542 | #endif |
---|
1543 | #ifdef KERBEROS_TGT_PASSING |
---|
1544 | #ifdef KRB5 |
---|
1545 | if (options.kerberos_tgt_passing) |
---|
1546 | auth_mask |= 1 << SSH_PASS_KERBEROS_TGT; |
---|
1547 | #endif |
---|
1548 | #endif |
---|
1549 | if (options.password_authentication) |
---|
1550 | auth_mask |= 1 << SSH_AUTH_PASSWORD; |
---|
1551 | packet_put_int(auth_mask); |
---|
1552 | |
---|
1553 | /* Send the packet and wait for it to be sent. */ |
---|
1554 | packet_send(); |
---|
1555 | packet_write_wait(); |
---|
1556 | |
---|
1557 | debug("Sent %d bit public key and %d bit host key.", |
---|
1558 | public_key.bits, sensitive_data.host_key.bits); |
---|
1559 | |
---|
1560 | /* Read clients reply (cipher type and session key). */ |
---|
1561 | packet_read_expect(SSH_CMSG_SESSION_KEY); |
---|
1562 | |
---|
1563 | /* Get cipher type. */ |
---|
1564 | cipher_type = packet_get_char(); |
---|
1565 | |
---|
1566 | /* Get check bytes from the packet. These must match those we sent earlier |
---|
1567 | with the public key packet. */ |
---|
1568 | for (i = 0; i < 8; i++) |
---|
1569 | if (check_bytes[i] != packet_get_char()) |
---|
1570 | packet_disconnect("IP Spoofing check bytes do not match."); |
---|
1571 | |
---|
1572 | debug("Encryption type: %.200s", cipher_name(cipher_type)); |
---|
1573 | |
---|
1574 | /* Get the encrypted integer. */ |
---|
1575 | mpz_init(&session_key_int); |
---|
1576 | packet_get_mp_int(&session_key_int); |
---|
1577 | |
---|
1578 | /* Get protocol flags. */ |
---|
1579 | protocol_flags = packet_get_int(); |
---|
1580 | packet_set_protocol_flags(protocol_flags); |
---|
1581 | |
---|
1582 | /* Decrypt it using our private server key and private host key (key with |
---|
1583 | larger modulus first). */ |
---|
1584 | if (mpz_cmp(&sensitive_data.private_key.n, &sensitive_data.host_key.n) > 0) |
---|
1585 | { |
---|
1586 | /* Private key has bigger modulus. */ |
---|
1587 | assert(sensitive_data.private_key.bits >= |
---|
1588 | sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED); |
---|
1589 | rsa_private_decrypt(&session_key_int, &session_key_int, |
---|
1590 | &sensitive_data.private_key); |
---|
1591 | rsa_private_decrypt(&session_key_int, &session_key_int, |
---|
1592 | &sensitive_data.host_key); |
---|
1593 | } |
---|
1594 | else |
---|
1595 | { |
---|
1596 | /* Host key has bigger modulus (or they are equal). */ |
---|
1597 | assert(sensitive_data.host_key.bits >= |
---|
1598 | sensitive_data.private_key.bits + SSH_KEY_BITS_RESERVED); |
---|
1599 | rsa_private_decrypt(&session_key_int, &session_key_int, |
---|
1600 | &sensitive_data.host_key); |
---|
1601 | rsa_private_decrypt(&session_key_int, &session_key_int, |
---|
1602 | &sensitive_data.private_key); |
---|
1603 | } |
---|
1604 | |
---|
1605 | /* Compute session id for this session. */ |
---|
1606 | compute_session_id(session_id, check_bytes, sensitive_data.host_key.bits, |
---|
1607 | &sensitive_data.host_key.n, |
---|
1608 | sensitive_data.private_key.bits, |
---|
1609 | &sensitive_data.private_key.n); |
---|
1610 | |
---|
1611 | /* Extract session key from the decrypted integer. The key is in the |
---|
1612 | least significant 256 bits of the integer; the first byte of the |
---|
1613 | key is in the highest bits. */ |
---|
1614 | mp_linearize_msb_first(session_key, sizeof(session_key), |
---|
1615 | &session_key_int); |
---|
1616 | |
---|
1617 | /* Xor the first 16 bytes of the session key with the session id. */ |
---|
1618 | for (i = 0; i < 16; i++) |
---|
1619 | session_key[i] ^= session_id[i]; |
---|
1620 | |
---|
1621 | /* Destroy the decrypted integer. It is no longer needed. */ |
---|
1622 | mpz_clear(&session_key_int); |
---|
1623 | |
---|
1624 | /* Set the session key. From this on all communications will be |
---|
1625 | encrypted. */ |
---|
1626 | packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, |
---|
1627 | cipher_type, 0); |
---|
1628 | |
---|
1629 | /* Destroy our copy of the session key. It is no longer needed. */ |
---|
1630 | memset(session_key, 0, sizeof(session_key)); |
---|
1631 | |
---|
1632 | debug("Received session key; encryption turned on."); |
---|
1633 | |
---|
1634 | /* Send an acknowledgement packet. Note that this packet is sent |
---|
1635 | encrypted. */ |
---|
1636 | packet_start(SSH_SMSG_SUCCESS); |
---|
1637 | packet_send(); |
---|
1638 | packet_write_wait(); |
---|
1639 | |
---|
1640 | /* Get the name of the user that we wish to log in as. */ |
---|
1641 | packet_read_expect(SSH_CMSG_USER); |
---|
1642 | |
---|
1643 | /* Get the user name. */ |
---|
1644 | user = packet_get_string(NULL); |
---|
1645 | |
---|
1646 | /* Destroy the private and public keys. They will no longer be needed. */ |
---|
1647 | rsa_clear_public_key(&public_key); |
---|
1648 | rsa_clear_private_key(&sensitive_data.private_key); |
---|
1649 | rsa_clear_private_key(&sensitive_data.host_key); |
---|
1650 | |
---|
1651 | /* Do the authentication. */ |
---|
1652 | do_authentication(user, privileged_port, cipher_type); |
---|
1653 | } |
---|
1654 | |
---|
1655 | /* Returns true if logging in as the specified user is permitted. Returns |
---|
1656 | false if login is not permitted (e.g., the account is expired). */ |
---|
1657 | |
---|
1658 | int login_permitted(char *user, struct passwd *pwd) |
---|
1659 | { |
---|
1660 | char passwd[6]; /* Only for account lock check */ |
---|
1661 | struct group *grp; |
---|
1662 | char *group; |
---|
1663 | |
---|
1664 | strncpy(passwd, pwd->pw_passwd, sizeof(passwd)); |
---|
1665 | passwd[sizeof(passwd) - 1] = '\0'; |
---|
1666 | #ifdef HAVE_USERSEC_H |
---|
1667 | { |
---|
1668 | char *expiration, current_time[100], normalized[100]; |
---|
1669 | int rlogin_permitted; |
---|
1670 | time_t t; |
---|
1671 | struct tm *tm; |
---|
1672 | if (setuserdb(S_READ) < 0) |
---|
1673 | { |
---|
1674 | debug("setuserdb S_READ failed: %.200s.", strerror(errno)); |
---|
1675 | return 0; |
---|
1676 | } |
---|
1677 | if (getuserattr(user, S_RLOGINCHK, &rlogin_permitted, SEC_BOOL) < 0) |
---|
1678 | { |
---|
1679 | debug("getuserattr S_RLOGINCHK failed: %.200s", strerror(errno)); |
---|
1680 | enduserdb(); |
---|
1681 | return 0; |
---|
1682 | } |
---|
1683 | if (getuserattr(user, S_EXPIRATION, &expiration, SEC_CHAR) < 0) |
---|
1684 | { |
---|
1685 | debug("getuserattr S_EXPIRATION failed: %.200s.", strerror(errno)); |
---|
1686 | enduserdb(); |
---|
1687 | return 0; |
---|
1688 | } |
---|
1689 | if (!rlogin_permitted) |
---|
1690 | { |
---|
1691 | debug("Remote logins to account %.100s not permitted by user profile.", |
---|
1692 | user); |
---|
1693 | enduserdb(); |
---|
1694 | return 0; |
---|
1695 | } |
---|
1696 | if (strcmp(expiration, "0") == 0) |
---|
1697 | { |
---|
1698 | /* The account does not expire - return success immediately. */ |
---|
1699 | enduserdb(); |
---|
1700 | return 1; |
---|
1701 | } |
---|
1702 | if (strlen(expiration) != 10) |
---|
1703 | { |
---|
1704 | debug("Account %.100s expiration date is in wrong format.", user); |
---|
1705 | enduserdb(); |
---|
1706 | return 0; |
---|
1707 | } |
---|
1708 | t = time(NULL); |
---|
1709 | tm = localtime(&t); |
---|
1710 | sprintf(current_time, "%04d%02d%02d%02d%02d", |
---|
1711 | tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, |
---|
1712 | tm->tm_hour, tm->tm_min); |
---|
1713 | if (expiration[8] < '7') /* Assume year < 70 is 20YY. */ |
---|
1714 | strcpy(normalized, "20"); |
---|
1715 | else |
---|
1716 | strcpy(normalized, "19"); |
---|
1717 | strcat(normalized, expiration + 8); |
---|
1718 | strcat(normalized, expiration); |
---|
1719 | normalized[12] = '\0'; |
---|
1720 | if (strcmp(normalized, current_time) < 0) |
---|
1721 | { |
---|
1722 | debug("Account %.100s has expired - access denied.", user); |
---|
1723 | enduserdb(); |
---|
1724 | return 0; |
---|
1725 | } |
---|
1726 | enduserdb(); |
---|
1727 | /* XXX No days_before_password_expires calculation here */ |
---|
1728 | } |
---|
1729 | #endif /* HAVE_USERSEC_H */ |
---|
1730 | #ifdef HAVE_ETC_SHADOW |
---|
1731 | { |
---|
1732 | struct spwd *sp; |
---|
1733 | |
---|
1734 | sp = getspnam(user); |
---|
1735 | #if defined(SECURE_RPC) && defined(NIS_PLUS) |
---|
1736 | if (geteuid() == UID_ROOT && pwd->pw_uid != UID_ROOT /* do we have guts? */ |
---|
1737 | && (!sp || !sp->sp_pwdp || !strcmp(sp->sp_pwdp,"*NP*"))) |
---|
1738 | { |
---|
1739 | if (seteuid(pwd->pw_uid) == UID_ROOT) |
---|
1740 | { |
---|
1741 | sp = getspnam(user); /* retry as user */ |
---|
1742 | seteuid(UID_ROOT); |
---|
1743 | } |
---|
1744 | } |
---|
1745 | #endif /* SECURE_RPC && NIS_PLUS */ |
---|
1746 | if (!sp) |
---|
1747 | { |
---|
1748 | /* |
---|
1749 | * Some systems, e.g.: IRIX, may or may not have /etc/shadow. |
---|
1750 | * Just check if there is one. If such system is also an YP |
---|
1751 | * client, then valid password might already be present in passwd |
---|
1752 | * structure. Just check if it's other than "x". Assume that |
---|
1753 | * YP server is always right if this is the case. |
---|
1754 | * appro@fy.chalmers.se |
---|
1755 | */ |
---|
1756 | struct stat sbf; |
---|
1757 | |
---|
1758 | if ((stat(SHADOW, &sbf) == 0) && !strcmp(pwd->pw_passwd,"x")) |
---|
1759 | { |
---|
1760 | debug("Can't find %.100s's shadow - access denied.", user); |
---|
1761 | endspent(); |
---|
1762 | return 0; |
---|
1763 | } |
---|
1764 | } |
---|
1765 | else |
---|
1766 | { |
---|
1767 | time_t today = time((time_t *)NULL)/24/60/60; /* what a day! */ |
---|
1768 | |
---|
1769 | #ifdef HAVE_STRUCT_SPWD_EXPIRE |
---|
1770 | /* Check for expiration date */ |
---|
1771 | if (sp->sp_expire > 0 && today > sp->sp_expire) |
---|
1772 | { |
---|
1773 | debug("Account %.100s has expired - access denied.", user); |
---|
1774 | endspent(); |
---|
1775 | return 0; |
---|
1776 | } |
---|
1777 | if (sp->sp_expire > 0) |
---|
1778 | { |
---|
1779 | days_before_account_expires = sp->sp_expire - today; |
---|
1780 | } |
---|
1781 | #endif |
---|
1782 | |
---|
1783 | #ifdef HAVE_STRUCT_SPWD_INACT |
---|
1784 | /* Check for last login */ |
---|
1785 | if (sp->sp_inact > 0) |
---|
1786 | { |
---|
1787 | char buf[64]; |
---|
1788 | unsigned long llt; |
---|
1789 | |
---|
1790 | llt = get_last_login_time(pwd->pw_uid, user, buf, sizeof(buf)); |
---|
1791 | if (llt && (today - llt/24/60/60) > sp->sp_inact) |
---|
1792 | { |
---|
1793 | debug("Account %.100s was inactive for more than %d days.", |
---|
1794 | user, sp->sp_inact); |
---|
1795 | endspent(); |
---|
1796 | return 0; |
---|
1797 | } |
---|
1798 | } |
---|
1799 | #endif |
---|
1800 | |
---|
1801 | /* Check if password is valid */ |
---|
1802 | if (sp->sp_lstchg == 0 || |
---|
1803 | (sp->sp_max > 0 && today > sp->sp_lstchg + sp->sp_max)) |
---|
1804 | { |
---|
1805 | debug("Account %.100s's password is too old - forced to change.", |
---|
1806 | user); |
---|
1807 | if (options.forced_passwd_change) |
---|
1808 | { |
---|
1809 | forced_command = xmalloc(sizeof(PASSWD_PATH) + |
---|
1810 | strlen(user) + 1); |
---|
1811 | sprintf(forced_command, "%s %s", PASSWD_PATH, user); |
---|
1812 | } |
---|
1813 | else |
---|
1814 | { |
---|
1815 | endspent(); |
---|
1816 | return 0; |
---|
1817 | } |
---|
1818 | } |
---|
1819 | else |
---|
1820 | { |
---|
1821 | if (sp->sp_max > 0) |
---|
1822 | { |
---|
1823 | days_before_password_expires = |
---|
1824 | sp->sp_lstchg + sp->sp_max - today; |
---|
1825 | } |
---|
1826 | } |
---|
1827 | strncpy(passwd, sp->sp_pwdp, sizeof(passwd)); |
---|
1828 | passwd[sizeof(passwd) - 1] = '\0'; |
---|
1829 | } |
---|
1830 | endspent(); |
---|
1831 | } |
---|
1832 | #endif /* HAVE_ETC_SHADOW */ |
---|
1833 | #ifdef __FreeBSD__ |
---|
1834 | { |
---|
1835 | time_t currtime; |
---|
1836 | |
---|
1837 | if (pwd->pw_change || pwd->pw_expire) |
---|
1838 | currtime = time(NULL); |
---|
1839 | |
---|
1840 | /* |
---|
1841 | * Check for an expired password |
---|
1842 | */ |
---|
1843 | if (pwd->pw_change && pwd->pw_change <= currtime) |
---|
1844 | { |
---|
1845 | debug("Account %.100s's password is too old - forced to change.", |
---|
1846 | user); |
---|
1847 | if (options.forced_passwd_change) |
---|
1848 | { |
---|
1849 | forced_command = xmalloc(sizeof(PASSWD_PATH) + strlen(user) + 1); |
---|
1850 | sprintf(forced_command, "%s %s", PASSWD_PATH, user); |
---|
1851 | } |
---|
1852 | else |
---|
1853 | { |
---|
1854 | return 0; |
---|
1855 | } |
---|
1856 | } |
---|
1857 | else |
---|
1858 | { |
---|
1859 | if (pwd->pw_change) |
---|
1860 | { |
---|
1861 | days_before_password_expires = (pwd->pw_change - currtime) / 86400; |
---|
1862 | } |
---|
1863 | } |
---|
1864 | |
---|
1865 | /* |
---|
1866 | * Check for expired account |
---|
1867 | */ |
---|
1868 | if (pwd->pw_expire && pwd->pw_expire <= currtime) |
---|
1869 | { |
---|
1870 | debug("Account %.100s has expired - access denied.", user); |
---|
1871 | return 0; |
---|
1872 | } |
---|
1873 | else |
---|
1874 | { |
---|
1875 | if (pwd->pw_expire) |
---|
1876 | { |
---|
1877 | days_before_account_expires = (pwd->pw_expire - currtime) / 86400; |
---|
1878 | } |
---|
1879 | } |
---|
1880 | } |
---|
1881 | #endif /* !FreeBSD */ |
---|
1882 | |
---|
1883 | #ifdef HAVE_HPUX_TCB_AUTH |
---|
1884 | { |
---|
1885 | struct pr_passwd *pr; |
---|
1886 | time_t expire, warntime; |
---|
1887 | short tries; |
---|
1888 | |
---|
1889 | pr = getprpwnam(user); |
---|
1890 | if (pr) |
---|
1891 | { |
---|
1892 | /* |
---|
1893 | * Check whether lock field exists & is set, if so |
---|
1894 | * deny the user access |
---|
1895 | */ |
---|
1896 | if ( pr->uflg.fg_lock && pr->ufld.fd_lock ) |
---|
1897 | { |
---|
1898 | debug("Account %.100s is locked.",user); |
---|
1899 | packet_send_debug("\n\tAdministrative lock on account"); |
---|
1900 | endprpwent(); |
---|
1901 | return 0; |
---|
1902 | } |
---|
1903 | /* |
---|
1904 | * Check whether account lifetime exceeded, if so |
---|
1905 | * deny the user access |
---|
1906 | */ |
---|
1907 | if ( pr->uflg.fg_acct_expire && time(NULL) > pr->ufld.fd_acct_expire ) |
---|
1908 | { |
---|
1909 | debug("Account %.100s lifetime exceeded.", user); |
---|
1910 | packet_send_debug("\n\tAccount lifetime exceeded"); |
---|
1911 | endprpwent(); |
---|
1912 | return 0; |
---|
1913 | } |
---|
1914 | /* |
---|
1915 | * Check whether pw_admin_num is set, if so |
---|
1916 | * force passwd change. |
---|
1917 | */ |
---|
1918 | if ( pr->uflg.fg_pw_admin_num && pr->ufld.fd_pw_admin_num ) |
---|
1919 | { |
---|
1920 | debug("Account %.100s requires passwd change",user); |
---|
1921 | if (options.forced_passwd_change) |
---|
1922 | { |
---|
1923 | forced_command = xmalloc(sizeof(PASSWD_PATH) + |
---|
1924 | strlen(user) + 1); |
---|
1925 | sprintf(forced_command, "%s %s", PASSWD_PATH, user); |
---|
1926 | options.permit_empty_passwd = 1; |
---|
1927 | } |
---|
1928 | else |
---|
1929 | { |
---|
1930 | endprpwent(); |
---|
1931 | return 0; |
---|
1932 | } |
---|
1933 | } |
---|
1934 | /* |
---|
1935 | * Check whether passwd aging is enabled for this user |
---|
1936 | * (either explicitly, i.e., flag set and value != 0, or |
---|
1937 | * system wide, sys flag set and sys value != 0). A user |
---|
1938 | * flag set and value == 0 means passwd aging explicitly |
---|
1939 | * disabled for this user. If passwd expired, force |
---|
1940 | * passwd change. |
---|
1941 | */ |
---|
1942 | if ( pr->uflg.fg_expire ) |
---|
1943 | expire = pr->ufld.fd_expire; |
---|
1944 | else if ( pr->sflg.fg_expire ) |
---|
1945 | expire = pr->sfld.fd_expire; |
---|
1946 | else |
---|
1947 | expire = 0; |
---|
1948 | if ( expire ) |
---|
1949 | { |
---|
1950 | days_before_password_expires = expire / 86400; |
---|
1951 | if ( pr->uflg.fg_pw_expire_warning ) |
---|
1952 | warntime = pr->ufld.fd_pw_expire_warning; |
---|
1953 | else if ( pr->sflg.fg_pw_expire_warning ) |
---|
1954 | warntime = pr->sfld.fd_pw_expire_warning; |
---|
1955 | else |
---|
1956 | warntime = 7*24*60*60; /* default to 7 days warning */ |
---|
1957 | if ( time(NULL) > pr->ufld.fd_schange + expire ) |
---|
1958 | { |
---|
1959 | debug("Account %.100s passwd expired, requires change", user); |
---|
1960 | if (options.forced_passwd_change) |
---|
1961 | { |
---|
1962 | forced_command = xmalloc(sizeof(PASSWD_PATH) + |
---|
1963 | strlen(user) + 1); |
---|
1964 | sprintf(forced_command, "%s %s", PASSWD_PATH, user); |
---|
1965 | } |
---|
1966 | else |
---|
1967 | { |
---|
1968 | endprpwent(); |
---|
1969 | return 0; |
---|
1970 | } |
---|
1971 | } |
---|
1972 | } |
---|
1973 | /* |
---|
1974 | * Check for inactivity. If set to disable inactive accounts, |
---|
1975 | * then we must deny access if inactive for said period of time. |
---|
1976 | */ |
---|
1977 | if ( pr->uflg.fg_max_llogin ) |
---|
1978 | expire = pr->ufld.fd_max_llogin; |
---|
1979 | else if ( pr->sflg.fg_max_llogin ) |
---|
1980 | expire = pr->sfld.fd_max_llogin; |
---|
1981 | else |
---|
1982 | expire = 0; |
---|
1983 | if ( expire && pr->ufld.fd_slogin |
---|
1984 | && time(NULL) > pr->ufld.fd_slogin + expire ) |
---|
1985 | { |
---|
1986 | debug("Account %.100s locked due to inactivity.", user); |
---|
1987 | packet_send_debug("\n\tAccount locked due to inactivity"); |
---|
1988 | endprpwent(); |
---|
1989 | return 0; |
---|
1990 | } |
---|
1991 | /* |
---|
1992 | * If configured to lock on too many unsuccessful login attempts, |
---|
1993 | * then check and deny access |
---|
1994 | */ |
---|
1995 | if ( pr->uflg.fg_max_tries ) |
---|
1996 | tries = pr->ufld.fd_max_tries; |
---|
1997 | else if ( pr->sflg.fg_max_tries ) |
---|
1998 | tries = pr->sfld.fd_max_tries; |
---|
1999 | else |
---|
2000 | tries = 0; |
---|
2001 | if ( tries && pr->ufld.fd_nlogins > tries ) |
---|
2002 | { |
---|
2003 | debug("Account %.100s locked, too many unsuccessful login attempts", |
---|
2004 | user); |
---|
2005 | packet_send_debug("\n\tToo many unsuccessful attempts"); |
---|
2006 | endprpwent(); |
---|
2007 | return 0; |
---|
2008 | } |
---|
2009 | } |
---|
2010 | endprpwent(); |
---|
2011 | } |
---|
2012 | #endif /* HAVE_HPUX_TCB_AUTH */ |
---|
2013 | |
---|
2014 | /* |
---|
2015 | * Check if account is locked. Check if encrypted password starts |
---|
2016 | * with "*LK*". |
---|
2017 | */ |
---|
2018 | { |
---|
2019 | if ((strncmp(passwd,"*LK*", 4) == 0) |
---|
2020 | #if defined(KERBEROS) && defined(KRB5) |
---|
2021 | && (options.kerberos_or_local_passwd != 0) |
---|
2022 | #endif /* defined(KERBEROS) && defined(KRB5) */ |
---|
2023 | ) |
---|
2024 | { |
---|
2025 | debug("Account %.100s is locked.", user); |
---|
2026 | return 0; |
---|
2027 | } |
---|
2028 | } |
---|
2029 | #ifdef CHECK_ETC_SHELLS |
---|
2030 | { |
---|
2031 | int invalid = 1; |
---|
2032 | char *shell = pwd->pw_shell, *etc_shell, *getusershell(); |
---|
2033 | |
---|
2034 | if (!shell || !*shell) |
---|
2035 | shell = DEFAULT_SHELL; |
---|
2036 | |
---|
2037 | while (invalid && (etc_shell = getusershell())) |
---|
2038 | invalid = strcmp(etc_shell,shell); |
---|
2039 | endusershell(); |
---|
2040 | |
---|
2041 | if (invalid) |
---|
2042 | { |
---|
2043 | debug("Account %.100s doesn't have valid shell", user); |
---|
2044 | return 0; |
---|
2045 | } |
---|
2046 | } |
---|
2047 | #endif /* CHECK_ETC_SHELLS */ |
---|
2048 | |
---|
2049 | /* here we check the AllowUser and DenyUser config options - SteveK */ |
---|
2050 | /* Check whether logins are permitted for this user. */ |
---|
2051 | if (options.num_allow_users > 0) |
---|
2052 | { |
---|
2053 | int i; |
---|
2054 | const char *hostname = get_canonical_hostname(); |
---|
2055 | const char *ipaddr = get_remote_ipaddr(); |
---|
2056 | |
---|
2057 | for (i = 0; i < options.num_allow_users; i++) |
---|
2058 | if (match_user(user, hostname, ipaddr, options.allow_users[i])) |
---|
2059 | break; |
---|
2060 | if (i >= options.num_allow_users) |
---|
2061 | { |
---|
2062 | log_msg("Connection for %.200s not allowed from %s\n", |
---|
2063 | user, get_canonical_hostname()); |
---|
2064 | return 0; |
---|
2065 | } |
---|
2066 | } |
---|
2067 | |
---|
2068 | /* Check whether logins are denied for this user. */ |
---|
2069 | if (options.num_deny_users > 0) |
---|
2070 | { |
---|
2071 | int i; |
---|
2072 | const char *hostname = get_canonical_hostname(); |
---|
2073 | const char *ipaddr = get_remote_ipaddr(); |
---|
2074 | |
---|
2075 | for (i = 0; i < options.num_deny_users; i++) |
---|
2076 | if (match_user(user, hostname, ipaddr, options.deny_users[i])) |
---|
2077 | { |
---|
2078 | log_msg("Connection for %.200s denied from %s\n", |
---|
2079 | user, get_canonical_hostname()); |
---|
2080 | return 0; |
---|
2081 | } |
---|
2082 | } |
---|
2083 | |
---|
2084 | /* Check whether logins are deneid for this group. */ |
---|
2085 | grp = getgrgid(pwd->pw_gid); |
---|
2086 | if (grp) |
---|
2087 | group = grp->gr_name; |
---|
2088 | else |
---|
2089 | { |
---|
2090 | log_msg("Unknown group id %d\n", pwd->pw_gid); |
---|
2091 | group = "none"; |
---|
2092 | } |
---|
2093 | |
---|
2094 | if (options.num_allow_groups > 0) |
---|
2095 | { |
---|
2096 | int i; |
---|
2097 | for (i = 0; i < options.num_allow_groups; i++) |
---|
2098 | if (match_pattern(group, options.allow_groups[i])) |
---|
2099 | break; |
---|
2100 | if (grp == NULL || i >= options.num_allow_groups) |
---|
2101 | { |
---|
2102 | log_msg("Connection for %.200s not allowed from %s\n", |
---|
2103 | group, get_canonical_hostname()); |
---|
2104 | return 0; |
---|
2105 | } |
---|
2106 | } |
---|
2107 | |
---|
2108 | /* Check whether logins are denied for this group. */ |
---|
2109 | if (options.num_deny_groups > 0) |
---|
2110 | { |
---|
2111 | int i; |
---|
2112 | for (i = 0; i < options.num_deny_groups; i++) |
---|
2113 | if (grp && match_pattern(group, options.deny_groups[i])) |
---|
2114 | { |
---|
2115 | log_msg("Connection for %.200s denied from %s\n", |
---|
2116 | group, get_canonical_hostname()); |
---|
2117 | return 0; |
---|
2118 | } |
---|
2119 | } |
---|
2120 | |
---|
2121 | return 1; |
---|
2122 | } |
---|
2123 | |
---|
2124 | /* This function is called by userfile_init after fork() to clean up sensitive |
---|
2125 | data. RSA keys have already been destroyed before we get here. However, |
---|
2126 | normal encryption keys and socket connections (access rights) need to |
---|
2127 | be destroyed. */ |
---|
2128 | |
---|
2129 | static void sshd_userfile_cleanup(void *context) |
---|
2130 | { |
---|
2131 | endpwent(); |
---|
2132 | |
---|
2133 | /* Close the connection descriptors; note that this is the child, and the |
---|
2134 | server will still have the socket open, and it is important that we |
---|
2135 | do not shutdown it. Note that the descriptors cannot be closed before |
---|
2136 | building the environment, as we call get_remote_ipaddr there. */ |
---|
2137 | if (packet_get_connection_in() == packet_get_connection_out()) |
---|
2138 | close(packet_get_connection_in()); |
---|
2139 | else |
---|
2140 | { |
---|
2141 | close(packet_get_connection_in()); |
---|
2142 | close(packet_get_connection_out()); |
---|
2143 | } |
---|
2144 | /* Close all descriptors related to channels. They will still remain |
---|
2145 | open in the parent. */ |
---|
2146 | channel_close_all(); |
---|
2147 | |
---|
2148 | /* Set dummy encryption key to clear key data from memory. This key will |
---|
2149 | never be used. */ |
---|
2150 | packet_set_encryption_key((void *)"0123456789ABCDEF0123456789ABCDEF", |
---|
2151 | 16, SSH_CIPHER_3DES, 0); |
---|
2152 | } |
---|
2153 | |
---|
2154 | /* Fails all authentication requests */ |
---|
2155 | void do_authentication_fail_loop(void) |
---|
2156 | { |
---|
2157 | /* The user does not exist. */ |
---|
2158 | packet_start(SSH_SMSG_FAILURE); |
---|
2159 | packet_send(); |
---|
2160 | packet_write_wait(); |
---|
2161 | |
---|
2162 | /* Keep reading packets, and always respond with a failure. This is to |
---|
2163 | avoid disclosing whether such a user really exists. */ |
---|
2164 | for (;;) |
---|
2165 | { |
---|
2166 | /* Read a packet. This will not return if the client disconnects. */ |
---|
2167 | (void) packet_read(); |
---|
2168 | packet_get_all(); |
---|
2169 | |
---|
2170 | /* Send failure. This should be indistinguishable from a failed |
---|
2171 | authentication. */ |
---|
2172 | packet_start(SSH_SMSG_FAILURE); |
---|
2173 | packet_send(); |
---|
2174 | packet_write_wait(); |
---|
2175 | } |
---|
2176 | /*NOTREACHED*/ |
---|
2177 | abort(); |
---|
2178 | } |
---|
2179 | |
---|
2180 | /* Performs authentication of an incoming connection. Session key has already |
---|
2181 | been exchanged and encryption is enabled. User is the user name to log |
---|
2182 | in as (received from the clinet). Privileged_port is true if the |
---|
2183 | connection comes from a privileged port (used for .rhosts authentication).*/ |
---|
2184 | |
---|
2185 | void do_authentication(char *user, int privileged_port, int cipher_type) |
---|
2186 | { |
---|
2187 | int type; |
---|
2188 | int authenticated = 0; |
---|
2189 | int authentication_type = 0; |
---|
2190 | char *password; |
---|
2191 | struct passwd *pw, *pw2, pwcopy; |
---|
2192 | char *client_user; |
---|
2193 | unsigned int client_host_key_bits; |
---|
2194 | MP_INT client_host_key_e, client_host_key_n; |
---|
2195 | int password_attempts = 0; |
---|
2196 | #if defined(KERBEROS) && defined(KRB5) |
---|
2197 | char kuser[128]; |
---|
2198 | krb5_principal client = 0, tkt_client = 0; |
---|
2199 | krb5_data krb5data; |
---|
2200 | #endif /* defined(KERBEROS) && defined(KRB5) */ |
---|
2201 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
2202 | login_cap_t *lc; |
---|
2203 | const char *hostname; |
---|
2204 | const char *ipaddr; |
---|
2205 | char *cap_hlist, *hp; |
---|
2206 | int perm_denied = 0; |
---|
2207 | |
---|
2208 | hostname = get_canonical_hostname(); |
---|
2209 | ipaddr = get_remote_ipaddr(); |
---|
2210 | #endif /* HAVE_LOGIN_CAP_H */ |
---|
2211 | int status, i; |
---|
2212 | char *filetext, *errmem; |
---|
2213 | const char *err; |
---|
2214 | |
---|
2215 | if (strlen(user) > 255) |
---|
2216 | do_authentication_fail_loop(); |
---|
2217 | |
---|
2218 | #if defined(KERBEROS) && defined(KRB5) |
---|
2219 | /* For KRB5 allow the user to input fully qualified name i.e. |
---|
2220 | "username@realm" as the local user name. Then use this name to call |
---|
2221 | out to krb5_aname_to_localname to find if there is a localname |
---|
2222 | for this user. By doing this local names do not have to match |
---|
2223 | kerberos network names. This comes in handy when doing cross realm |
---|
2224 | authentication, or when you want auth_password to authenticate |
---|
2225 | to the users local realm. Pass client down to auth_password(), |
---|
2226 | auth_kerberos() and auth_kerberos_tgt() */ |
---|
2227 | |
---|
2228 | if (!ssh_context) |
---|
2229 | { |
---|
2230 | krb5_error_code r; |
---|
2231 | |
---|
2232 | if ((r = krb5_init_context(&ssh_context))) |
---|
2233 | fatal("Kerberos V5: %s while initializing krb5.", |
---|
2234 | error_message(r)); |
---|
2235 | krb5_init_ets(ssh_context); |
---|
2236 | } |
---|
2237 | debug("Connection attempt for %.100s from %s.", user, |
---|
2238 | get_canonical_hostname()); |
---|
2239 | |
---|
2240 | if (strchr(user,'@') || strchr(user,'%')) |
---|
2241 | { |
---|
2242 | if (strchr(user,'%')) |
---|
2243 | *strchr(user,'%') = '@'; |
---|
2244 | krb5_parse_name(ssh_context, user, &client); |
---|
2245 | if (!(krb5_aname_to_localname(ssh_context, client, |
---|
2246 | sizeof(kuser), kuser))) |
---|
2247 | user = kuser; |
---|
2248 | } |
---|
2249 | else |
---|
2250 | krb5_parse_name(ssh_context, user, &client); |
---|
2251 | #endif /* defined(KERBEROS) && defined(KRB5) */ |
---|
2252 | |
---|
2253 | /* Verify that the user is a valid user. We disallow usernames starting |
---|
2254 | with any characters that are commonly used to start NIS entries. */ |
---|
2255 | status = al_login_allowed(user, 1, &al_local_acct, &filetext); |
---|
2256 | if (status != AL_SUCCESS) |
---|
2257 | { |
---|
2258 | /* We don't want to use `packet_disconnect', because it will syslog |
---|
2259 | at LOG_ERR. Ssh doesn't provide a primitive way to give an |
---|
2260 | informative message and disconnect without any bad feelings... */ |
---|
2261 | |
---|
2262 | char *buf; |
---|
2263 | |
---|
2264 | err = al_strerror(status, &errmem); |
---|
2265 | if (filetext && *filetext) |
---|
2266 | { |
---|
2267 | buf = xmalloc(40 + strlen(err) + strlen(filetext)); |
---|
2268 | sprintf(buf, "You are not allowed to log in here: %s\n%s", |
---|
2269 | err, filetext); |
---|
2270 | } |
---|
2271 | else |
---|
2272 | { |
---|
2273 | buf = xmalloc(40 + strlen(err)); |
---|
2274 | sprintf(buf, "You are not allowed to log in here: %s\n", err); |
---|
2275 | } |
---|
2276 | packet_start(SSH_MSG_DISCONNECT); |
---|
2277 | packet_put_string(buf, strlen(buf)); |
---|
2278 | packet_send(); |
---|
2279 | packet_write_wait(); |
---|
2280 | |
---|
2281 | fatal_severity(SYSLOG_SEVERITY_INFO, "Login denied: %s", err); |
---|
2282 | /* not reached */ |
---|
2283 | } |
---|
2284 | if (!al_local_acct) |
---|
2285 | { |
---|
2286 | status = al_acct_create(user, NULL, getpid(), 0, 0, NULL); |
---|
2287 | if (status != AL_SUCCESS && debug_flag) |
---|
2288 | { |
---|
2289 | err = al_strerror(status, &errmem); |
---|
2290 | debug("al_acct_create failed for user %s: %s", user, err); |
---|
2291 | al_free_errmem(errmem); |
---|
2292 | } |
---|
2293 | al_user = xstrdup(user); |
---|
2294 | atexit(al_cleanup); |
---|
2295 | } |
---|
2296 | pw = getpwnam(user); |
---|
2297 | |
---|
2298 | if (!pw || user[0] == '-' || user[0] == '+' || user[0] == '@' || |
---|
2299 | !login_permitted(user, pw)) |
---|
2300 | do_authentication_fail_loop(); |
---|
2301 | |
---|
2302 | /* Take a copy of the returned structure. */ |
---|
2303 | memset(&pwcopy, 0, sizeof(pwcopy)); |
---|
2304 | pwcopy.pw_name = xstrdup(pw->pw_name); |
---|
2305 | pwcopy.pw_passwd = xstrdup(pw->pw_passwd); |
---|
2306 | pwcopy.pw_uid = pw->pw_uid; |
---|
2307 | pwcopy.pw_gid = pw->pw_gid; |
---|
2308 | #if (defined (__bsdi__) && _BSDI_VERSION >= 199510) || (defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) |
---|
2309 | pwcopy.pw_class = xstrdup(pw->pw_class); |
---|
2310 | pwcopy.pw_change = pw->pw_change; |
---|
2311 | pwcopy.pw_expire = pw->pw_expire; |
---|
2312 | #endif /* __bsdi__ && _BSDI_VERSION >= 199510 */ |
---|
2313 | pwcopy.pw_dir = xstrdup(pw->pw_dir); |
---|
2314 | pwcopy.pw_shell = xstrdup(pw->pw_shell); |
---|
2315 | pw = &pwcopy; |
---|
2316 | |
---|
2317 | /* Start a child process running on the user's uid. It will be used to |
---|
2318 | read files in the user's directory. Note that the private host |
---|
2319 | key has already been cleared when this is called. We still want to |
---|
2320 | clean up at least the encryption keys. */ |
---|
2321 | userfile_init(pw->pw_name, pw->pw_uid, pw->pw_gid, |
---|
2322 | sshd_userfile_cleanup, NULL); |
---|
2323 | |
---|
2324 | /* If we are not running as root, the user must have the same uid as the |
---|
2325 | server. */ |
---|
2326 | if (getuid() != UID_ROOT && pw->pw_uid != getuid()) |
---|
2327 | packet_disconnect("Cannot change user when server not running as root."); |
---|
2328 | |
---|
2329 | debug("Attempting authentication for %.100s.", user); |
---|
2330 | |
---|
2331 | #if defined (KERBEROS) && defined (KRB5) |
---|
2332 | if (!options.kerberos_authentication && options.password_authentication && |
---|
2333 | auth_password(user, "", 0)) |
---|
2334 | #else /* defined(KERBEROS) && defined(KRB5) */ |
---|
2335 | /* If the user has no password, accept authentication immediately. */ |
---|
2336 | if (options.password_authentication && auth_password(user, "")) |
---|
2337 | #endif /* defined(KERBEROS) && defined(KRB5) */ |
---|
2338 | { |
---|
2339 | /* Authentication with empty password succeeded. */ |
---|
2340 | debug("Login for user %.100s accepted without authentication.", user); |
---|
2341 | authentication_type = SSH_AUTH_PASSWORD; |
---|
2342 | authenticated = 1; |
---|
2343 | /* Success packet will be sent after loop below. */ |
---|
2344 | } |
---|
2345 | else |
---|
2346 | { |
---|
2347 | /* Indicate that authentication is needed. */ |
---|
2348 | packet_start(SSH_SMSG_FAILURE); |
---|
2349 | packet_send(); |
---|
2350 | packet_write_wait(); |
---|
2351 | } |
---|
2352 | |
---|
2353 | /* Loop until the user has been authenticated or the connection is closed. */ |
---|
2354 | while (!authenticated) |
---|
2355 | { |
---|
2356 | /* Get a packet from the client. */ |
---|
2357 | type = packet_read(); |
---|
2358 | |
---|
2359 | /* Process the packet. */ |
---|
2360 | switch (type) |
---|
2361 | { |
---|
2362 | #ifdef KERBEROS_TGT_PASSING |
---|
2363 | #ifdef KRB5 |
---|
2364 | case SSH_CMSG_HAVE_KERBEROS_TGT: |
---|
2365 | if (!options.kerberos_tgt_passing || |
---|
2366 | (!(options.kerberos_authentication || |
---|
2367 | options.password_authentication || |
---|
2368 | options.rsa_authentication))) |
---|
2369 | { |
---|
2370 | packet_get_all(); |
---|
2371 | log_msg("Kerberos tgt passing disabled."); |
---|
2372 | break; |
---|
2373 | } |
---|
2374 | |
---|
2375 | /* Accept Kerberos tgt. */ |
---|
2376 | krb5data.data = packet_get_string((unsigned int *) &krb5data.length); |
---|
2377 | |
---|
2378 | if (!auth_kerberos_tgt(user, &krb5data, client) || |
---|
2379 | !krb5_kuserok(ssh_context, client, user)){ |
---|
2380 | log_msg("Kerberos tgt REFUSED for %s", user); |
---|
2381 | debug("Kerberos tgt REFUSED for %s", user); |
---|
2382 | } |
---|
2383 | free(krb5data.data); |
---|
2384 | #endif |
---|
2385 | continue; |
---|
2386 | #endif /* KERBEROS_TGT_PASSING */ |
---|
2387 | |
---|
2388 | #ifdef KERBEROS |
---|
2389 | #ifdef KRB5 |
---|
2390 | case SSH_CMSG_AUTH_KERBEROS: |
---|
2391 | if (!options.kerberos_authentication) |
---|
2392 | { |
---|
2393 | packet_get_all(); |
---|
2394 | log_msg("Kerberos authentication disabled."); |
---|
2395 | break; |
---|
2396 | } |
---|
2397 | /* Try Kerberos authentication. */ |
---|
2398 | krb5data.data = packet_get_string((unsigned int *) &krb5data.length); |
---|
2399 | if (auth_kerberos(user, &krb5data, &tkt_client)) |
---|
2400 | { |
---|
2401 | char *tkt_user; |
---|
2402 | |
---|
2403 | free(krb5data.data); |
---|
2404 | krb5_unparse_name(ssh_context, tkt_client, &tkt_user); |
---|
2405 | |
---|
2406 | /* Check ~/.klogin authorization now. */ |
---|
2407 | if (krb5_kuserok(ssh_context, tkt_client, user)) |
---|
2408 | { |
---|
2409 | if (client) |
---|
2410 | krb5_free_principal(ssh_context, client); |
---|
2411 | client = tkt_client; |
---|
2412 | /* Client has successfully authenticated to us. */ |
---|
2413 | log_msg("Kerberos authentication accepted %.100s for login to account %.100s from %.200s", |
---|
2414 | tkt_user, user, get_canonical_hostname()); |
---|
2415 | authentication_type = SSH_AUTH_KERBEROS; |
---|
2416 | authenticated = 1; |
---|
2417 | break; |
---|
2418 | } |
---|
2419 | else |
---|
2420 | { |
---|
2421 | krb5_free_principal(ssh_context, tkt_client); |
---|
2422 | packet_send_debug("Kerberos authorization failed."); |
---|
2423 | log_msg( "Kerberos authorization failed for %.100s for login to account %.100s from %.200s.", |
---|
2424 | tkt_user, user, get_canonical_hostname()); |
---|
2425 | } |
---|
2426 | free(tkt_user); |
---|
2427 | } |
---|
2428 | #endif /* KRB5 */ |
---|
2429 | debug("Kerberos authentication failed for %.100s from %.200s", |
---|
2430 | user, get_canonical_hostname()); |
---|
2431 | break; |
---|
2432 | #endif /* KERBEROS */ |
---|
2433 | |
---|
2434 | case SSH_CMSG_AUTH_RHOSTS: |
---|
2435 | if (!options.rhosts_authentication) |
---|
2436 | { |
---|
2437 | packet_get_all(); |
---|
2438 | log_msg("Rhosts authentication disabled."); |
---|
2439 | break; |
---|
2440 | } |
---|
2441 | |
---|
2442 | /* Rhosts authentication (also uses /etc/hosts.equiv). */ |
---|
2443 | if (!privileged_port) |
---|
2444 | { |
---|
2445 | packet_get_all(); |
---|
2446 | log_msg("Rhosts authentication not available for connections from unprivileged port."); |
---|
2447 | break; |
---|
2448 | } |
---|
2449 | |
---|
2450 | /* Get client user name. Note that we just have to trust the client; |
---|
2451 | this is one reason why rhosts authentication is insecure. |
---|
2452 | (Another is IP-spoofing on a local network.) */ |
---|
2453 | client_user = packet_get_string(NULL); |
---|
2454 | |
---|
2455 | /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ |
---|
2456 | if (auth_rhosts(pw, client_user, options.ignore_rhosts, |
---|
2457 | options.ignore_root_rhosts, |
---|
2458 | options.strict_modes)) |
---|
2459 | { |
---|
2460 | /* Authentication accepted. */ |
---|
2461 | log_msg("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.", |
---|
2462 | user, client_user, get_canonical_hostname()); |
---|
2463 | authentication_type = SSH_AUTH_RHOSTS; |
---|
2464 | authenticated = 1; |
---|
2465 | remote_user_name = client_user; |
---|
2466 | break; |
---|
2467 | } |
---|
2468 | debug("Rhosts authentication failed for '%.100s', remote '%.100s', host '%.200s'.", |
---|
2469 | user, client_user, get_canonical_hostname()); |
---|
2470 | xfree(client_user); |
---|
2471 | break; |
---|
2472 | |
---|
2473 | case SSH_CMSG_AUTH_RHOSTS_RSA: |
---|
2474 | if (!options.rhosts_rsa_authentication) |
---|
2475 | { |
---|
2476 | packet_get_all(); |
---|
2477 | log_msg("Rhosts with RSA authentication disabled."); |
---|
2478 | break; |
---|
2479 | } |
---|
2480 | |
---|
2481 | /* Rhosts authentication (also uses /etc/hosts.equiv) with RSA |
---|
2482 | host authentication. */ |
---|
2483 | if (!privileged_port) |
---|
2484 | { |
---|
2485 | packet_get_all(); |
---|
2486 | log_msg("RhostsRsa authentication not available for connections from unprivileged port."); |
---|
2487 | break; |
---|
2488 | } |
---|
2489 | if (cipher_type == SSH_CIPHER_NONE) |
---|
2490 | { |
---|
2491 | packet_get_all(); |
---|
2492 | log_msg("RhostsRsa authentication not available for unencrypted session."); |
---|
2493 | break; |
---|
2494 | } |
---|
2495 | if (cipher_type == SSH_CIPHER_ARCFOUR) |
---|
2496 | { |
---|
2497 | packet_get_all(); |
---|
2498 | log_msg("RhostsRsa authentication not available for session encrypted with arcfour."); |
---|
2499 | break; |
---|
2500 | } |
---|
2501 | |
---|
2502 | /* Get client user name. Note that we just have to trust the client; |
---|
2503 | root on the client machine can claim to be any user. */ |
---|
2504 | client_user = packet_get_string(NULL); |
---|
2505 | |
---|
2506 | /* Get the client host key. */ |
---|
2507 | mpz_init(&client_host_key_e); |
---|
2508 | mpz_init(&client_host_key_n); |
---|
2509 | client_host_key_bits = packet_get_int(); |
---|
2510 | packet_get_mp_int(&client_host_key_e); |
---|
2511 | packet_get_mp_int(&client_host_key_n); |
---|
2512 | |
---|
2513 | /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ |
---|
2514 | if (auth_rhosts_rsa(&sensitive_data.random_state, |
---|
2515 | pw, client_user, |
---|
2516 | client_host_key_bits, &client_host_key_e, |
---|
2517 | &client_host_key_n, options.ignore_rhosts, |
---|
2518 | options.ignore_root_rhosts, |
---|
2519 | options.strict_modes)) |
---|
2520 | { |
---|
2521 | /* Authentication accepted. */ |
---|
2522 | authentication_type = SSH_AUTH_RHOSTS_RSA; |
---|
2523 | authenticated = 1; |
---|
2524 | remote_user_name = client_user; |
---|
2525 | mpz_clear(&client_host_key_e); |
---|
2526 | mpz_clear(&client_host_key_n); |
---|
2527 | break; |
---|
2528 | } |
---|
2529 | debug("RhostsRSA authentication failed for '%.100s', remote '%.100s', host '%.200s'.", |
---|
2530 | user, client_user, get_canonical_hostname()); |
---|
2531 | xfree(client_user); |
---|
2532 | mpz_clear(&client_host_key_e); |
---|
2533 | mpz_clear(&client_host_key_n); |
---|
2534 | break; |
---|
2535 | |
---|
2536 | case SSH_CMSG_AUTH_RSA: |
---|
2537 | if (!options.rsa_authentication) |
---|
2538 | { |
---|
2539 | packet_get_all(); |
---|
2540 | log_msg("RSA authentication disabled."); |
---|
2541 | break; |
---|
2542 | } |
---|
2543 | |
---|
2544 | /* RSA authentication requested. */ |
---|
2545 | { |
---|
2546 | MP_INT n; |
---|
2547 | mpz_init(&n); |
---|
2548 | packet_get_mp_int(&n); |
---|
2549 | if (auth_rsa(pw, &n, &sensitive_data.random_state, |
---|
2550 | options.strict_modes)) |
---|
2551 | { |
---|
2552 | /* Successful authentication. */ |
---|
2553 | mpz_clear(&n); |
---|
2554 | log_msg("RSA authentication for %.100s accepted.", user); |
---|
2555 | authentication_type = SSH_AUTH_RSA; |
---|
2556 | authenticated = 1; |
---|
2557 | break; |
---|
2558 | } |
---|
2559 | mpz_clear(&n); |
---|
2560 | debug("RSA authentication for %.100s failed.", user); |
---|
2561 | } |
---|
2562 | break; |
---|
2563 | |
---|
2564 | #ifdef HAVE_TIS |
---|
2565 | case SSH_CMSG_AUTH_TIS: |
---|
2566 | /* Support for TIS authentication server |
---|
2567 | Contributed by Andre April <Andre.April@cediti.be>. */ |
---|
2568 | debug("TIS Authentication..."); |
---|
2569 | if (!options.tis_authentication) { |
---|
2570 | packet_get_all(); |
---|
2571 | log_msg("Tis authsrv authentication disabled."); |
---|
2572 | break; |
---|
2573 | } else { |
---|
2574 | char buf[128]; |
---|
2575 | char prompt[128]; |
---|
2576 | char mapping[128]; |
---|
2577 | FILE *f; |
---|
2578 | int found = 0; |
---|
2579 | char *key, *value, *resp; |
---|
2580 | Cfg* cfg; |
---|
2581 | |
---|
2582 | /* Tis authsrvr authentication requested */ |
---|
2583 | /* Asks Tis server for challenge */ |
---|
2584 | cfg = cfg_read("sshd"); |
---|
2585 | auth_open(cfg); |
---|
2586 | if (auth_recv(buf, sizeof(buf))) { |
---|
2587 | log_msg("Cannot connect to authentication server"); |
---|
2588 | packet_start(SSH_SMSG_FAILURE); |
---|
2589 | packet_send(); |
---|
2590 | packet_write_wait(); |
---|
2591 | break; |
---|
2592 | } |
---|
2593 | if (strncmp(buf, "Authsrv ready", 13)) { |
---|
2594 | auth_close(); |
---|
2595 | log_msg("Bad response from authentication server"); |
---|
2596 | packet_start(SSH_SMSG_FAILURE); |
---|
2597 | packet_send(); |
---|
2598 | packet_write_wait(); |
---|
2599 | break; |
---|
2600 | } |
---|
2601 | |
---|
2602 | /* If /etc/sshd_tis.map exists, try to find in that file |
---|
2603 | the name in the Tis database corresponding to "user". |
---|
2604 | It the file does not exist or "user" is not found in the |
---|
2605 | file, both names are supposed to be the same. */ |
---|
2606 | f = fopen(TIS_MAP_FILE, "r"); |
---|
2607 | if (f != 0) { |
---|
2608 | debug("searching for %s in /etc/sshd_tis.map", user); |
---|
2609 | while (fgets(mapping, 128, f)) { |
---|
2610 | mapping[strlen(mapping)-1] = '\0'; /* suppress '\n' */ |
---|
2611 | key = strtok(mapping, ":"); |
---|
2612 | value = strtok(0, ":"); |
---|
2613 | if (!strcmp(key, user)) { |
---|
2614 | found = 1; |
---|
2615 | debug("user %s is mapped to %s", user, value); |
---|
2616 | break; |
---|
2617 | } |
---|
2618 | } |
---|
2619 | } else { |
---|
2620 | debug("cannot open /etc/sshd_tis.map"); |
---|
2621 | } |
---|
2622 | if (found && (value != 0)) { |
---|
2623 | /* Limit user name to 100 characters to prevent buffer |
---|
2624 | overflow. Who is going to use a longer name, anyway? */ |
---|
2625 | if (strlen(value) > 100) { |
---|
2626 | log_msg("User name longer than 100 characters!!!"); |
---|
2627 | break; /* Authentication fails */ |
---|
2628 | } |
---|
2629 | debug("asking authorization for %s", value); |
---|
2630 | sprintf(buf, "authorize %s sshd", value); |
---|
2631 | debug("string sent to server: '%s'", buf); |
---|
2632 | } else { |
---|
2633 | if (strlen(user) > 100) { |
---|
2634 | /* Should not happen since do_authentication already |
---|
2635 | checked that "user" is a valid user and Unix |
---|
2636 | usernames are limited to 8 chars */ |
---|
2637 | log_msg("User name longer than 100 characters!!!"); |
---|
2638 | break; /* Authentication fails */ |
---|
2639 | } |
---|
2640 | debug("asking authorization for %s", user); |
---|
2641 | sprintf(buf, "authorize %s sshd", user); |
---|
2642 | } |
---|
2643 | auth_send(buf); |
---|
2644 | auth_recv(buf, 100); /* More than enough for the challenge */ |
---|
2645 | |
---|
2646 | if (!strncmp(buf, "challenge ", 10) || |
---|
2647 | !strncmp(buf, "chalnecho ", 10)) { |
---|
2648 | sprintf(prompt,"Challenge \"%.100s\": ",&buf[10]); |
---|
2649 | debug("TIS challenge %s", buf); |
---|
2650 | packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); |
---|
2651 | packet_put_string(prompt, strlen(prompt)); |
---|
2652 | packet_send(); |
---|
2653 | packet_write_wait(); |
---|
2654 | } else { |
---|
2655 | if (!strncmp(buf, "password", 8)) { |
---|
2656 | debug("TIS password"); |
---|
2657 | packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); |
---|
2658 | packet_put_string("Password: ", 10); |
---|
2659 | packet_send(); |
---|
2660 | packet_write_wait(); |
---|
2661 | } else { |
---|
2662 | /* Unknown user */ |
---|
2663 | auth_close(); |
---|
2664 | debug("Unknown user from authentication server"); |
---|
2665 | break; |
---|
2666 | } |
---|
2667 | } |
---|
2668 | type = packet_read(); |
---|
2669 | if (type != SSH_CMSG_AUTH_TIS_RESPONSE) { |
---|
2670 | packet_get_all(); |
---|
2671 | auth_close(); |
---|
2672 | log_msg("Protocol error: got %d in respsonse to TIS challenge", |
---|
2673 | type); |
---|
2674 | break; |
---|
2675 | } |
---|
2676 | password = packet_get_string(NULL); |
---|
2677 | resp = xmalloc(strlen(password) + 12); |
---|
2678 | sprintf(resp,"response '%s'",password); |
---|
2679 | auth_send(resp); |
---|
2680 | xfree(resp); |
---|
2681 | auth_recv(buf, sizeof(buf)); |
---|
2682 | debug("response from authsrvr = %s",buf); |
---|
2683 | if (!strncmp(buf, "ok", 2)) { |
---|
2684 | auth_close(); |
---|
2685 | memset(password, 0, strlen(password)); |
---|
2686 | xfree(password); |
---|
2687 | authentication_type = SSH_AUTH_TIS; |
---|
2688 | authenticated = 1; |
---|
2689 | break; |
---|
2690 | } else { |
---|
2691 | debug("TIS authentication for %s failed",user); |
---|
2692 | memset(password, 0, strlen(password)); |
---|
2693 | xfree(password); |
---|
2694 | break; |
---|
2695 | } |
---|
2696 | } |
---|
2697 | break; /* TIS authsrv authentication not supported */ |
---|
2698 | #endif |
---|
2699 | case SSH_CMSG_AUTH_PASSWORD: |
---|
2700 | if (!options.password_authentication) |
---|
2701 | { |
---|
2702 | packet_get_all(); |
---|
2703 | log_msg("Password authentication disabled."); |
---|
2704 | break; |
---|
2705 | } |
---|
2706 | if (cipher_type == SSH_CIPHER_NONE) |
---|
2707 | { |
---|
2708 | packet_get_all(); |
---|
2709 | log_msg("Password authentication not available for unencrypted session."); |
---|
2710 | break; |
---|
2711 | } |
---|
2712 | |
---|
2713 | /* Password authentication requested. */ |
---|
2714 | /* Read user password. It is in plain text, but was transmitted |
---|
2715 | over the encrypted channel so it is not visible to an outside |
---|
2716 | observer. */ |
---|
2717 | password = packet_get_string(NULL); |
---|
2718 | |
---|
2719 | if (password_attempts >= 5) |
---|
2720 | { /* Too many password authentication attempts. */ |
---|
2721 | packet_disconnect("Too many password authentication attempts from %.100s for user %.100s.", |
---|
2722 | get_canonical_hostname(), user); |
---|
2723 | /*NOTREACHED*/ |
---|
2724 | } |
---|
2725 | |
---|
2726 | /* Count password authentication attempts, and log if appropriate. */ |
---|
2727 | if (password_attempts > 0) |
---|
2728 | { |
---|
2729 | /* Log failures if attempted more than once. */ |
---|
2730 | debug("Password authentication failed for user %.100s from %.100s.", |
---|
2731 | user, get_canonical_hostname()); |
---|
2732 | } |
---|
2733 | password_attempts++; |
---|
2734 | |
---|
2735 | /* Try authentication with the password. */ |
---|
2736 | #if defined(KERBEROS) && defined(KRB5) |
---|
2737 | if (auth_password(user, password, client)) |
---|
2738 | #else /* defined(KERBEROS) && defined(KRB5) */ |
---|
2739 | if (auth_password(user, password)) |
---|
2740 | #endif /* defined(KERBEROS) && defined(KRB5) */ |
---|
2741 | { |
---|
2742 | /* Successful authentication. */ |
---|
2743 | /* Clear the password from memory. */ |
---|
2744 | memset(password, 0, strlen(password)); |
---|
2745 | xfree(password); |
---|
2746 | log_msg("Password authentication for %.100s accepted.", user); |
---|
2747 | authentication_type = SSH_AUTH_PASSWORD; |
---|
2748 | authenticated = 1; |
---|
2749 | break; |
---|
2750 | } |
---|
2751 | debug("Password authentication for %.100s failed.", user); |
---|
2752 | memset(password, 0, strlen(password)); |
---|
2753 | xfree(password); |
---|
2754 | break; |
---|
2755 | |
---|
2756 | default: |
---|
2757 | /* Any unknown messages will be ignored (and failure returned) |
---|
2758 | during authentication. */ |
---|
2759 | packet_get_all(); |
---|
2760 | log_msg("Unknown message during authentication: type %d", type); |
---|
2761 | break; /* Respond with a failure message. */ |
---|
2762 | } |
---|
2763 | /* If successfully authenticated, break out of loop. */ |
---|
2764 | if (authenticated) |
---|
2765 | break; |
---|
2766 | |
---|
2767 | #ifdef KERBEROS |
---|
2768 | /* If you forwarded a ticket you get one shot for proper |
---|
2769 | authentication. */ |
---|
2770 | /* If tgt was passed, destroy it */ |
---|
2771 | if (ticket){ |
---|
2772 | if (strcmp(ticket,"none")) |
---|
2773 | { |
---|
2774 | krb5_ccache ccache; |
---|
2775 | if (!krb5_cc_resolve(ssh_context, ticket, &ccache)) |
---|
2776 | krb5_cc_destroy(ssh_context, ccache); |
---|
2777 | dest_tkt(); |
---|
2778 | } |
---|
2779 | else |
---|
2780 | ticket = NULL; |
---|
2781 | } |
---|
2782 | #endif /* KERBEROS */ |
---|
2783 | |
---|
2784 | /* Send a message indicating that the authentication attempt failed. */ |
---|
2785 | packet_start(SSH_SMSG_FAILURE); |
---|
2786 | packet_send(); |
---|
2787 | packet_write_wait(); |
---|
2788 | } |
---|
2789 | |
---|
2790 | /* Check if the user is logging in as root and root logins are disallowed. */ |
---|
2791 | if (pw->pw_uid == UID_ROOT && options.permit_root_login == 1) |
---|
2792 | { |
---|
2793 | if (authentication_type == SSH_AUTH_PASSWORD) |
---|
2794 | packet_disconnect("ROOT LOGIN REFUSED FROM %.200s", |
---|
2795 | get_canonical_hostname()); |
---|
2796 | } |
---|
2797 | else |
---|
2798 | if (pw->pw_uid == UID_ROOT && options.permit_root_login == 0) |
---|
2799 | { |
---|
2800 | if (forced_command) |
---|
2801 | log_msg("Root login accepted for forced command.", forced_command); |
---|
2802 | else |
---|
2803 | packet_disconnect("ROOT LOGIN REFUSED FROM %.200s", |
---|
2804 | get_canonical_hostname()); |
---|
2805 | } |
---|
2806 | |
---|
2807 | #if defined (__FreeBSD__) && defined (HAVE_LOGIN_CAP_H) |
---|
2808 | |
---|
2809 | lc = login_getclass(pw->pw_class); |
---|
2810 | |
---|
2811 | /* Check if the user's login class allows them to log in |
---|
2812 | * from the remote host. |
---|
2813 | */ |
---|
2814 | if((cap_hlist = login_getcapstr(lc, "host.deny", NULL, NULL)) != NULL) |
---|
2815 | { |
---|
2816 | hp = strtok(cap_hlist, ","); |
---|
2817 | while(hp != NULL) |
---|
2818 | { |
---|
2819 | if (match_host(hostname, ipaddr, hp)) |
---|
2820 | perm_denied = 1; |
---|
2821 | hp = strtok(NULL, ","); |
---|
2822 | } |
---|
2823 | } |
---|
2824 | if((!perm_denied) && |
---|
2825 | ((cap_hlist = login_getcapstr(lc, "host.allow", NULL, NULL)) != NULL)) |
---|
2826 | { |
---|
2827 | perm_denied = 1; /* Set default assuming the worst. */ |
---|
2828 | hp = strtok(cap_hlist, ","); |
---|
2829 | while(hp != NULL) |
---|
2830 | { |
---|
2831 | if(match_host(hostname, ipaddr, hp)) |
---|
2832 | perm_denied = 0; |
---|
2833 | hp = strtok(NULL,","); |
---|
2834 | } |
---|
2835 | } |
---|
2836 | login_close(lc); |
---|
2837 | if(perm_denied) |
---|
2838 | { |
---|
2839 | const char *hostname; |
---|
2840 | |
---|
2841 | hostname = get_canonical_hostname(); |
---|
2842 | log_severity(SYSLOG_SEVERITY_NOTICE, |
---|
2843 | "Denied connection for %.200s from %.200s [%.200s].\n", |
---|
2844 | pw->pw_name, hostname, ipaddr); |
---|
2845 | packet_disconnect("Sorry, you are not allowed to connect."); |
---|
2846 | } |
---|
2847 | #endif |
---|
2848 | |
---|
2849 | /* Log root logins with severity NOTICE. */ |
---|
2850 | if (pw->pw_uid == UID_ROOT) |
---|
2851 | log_severity(SYSLOG_SEVERITY_NOTICE, "ROOT LOGIN as '%.100s' from %.100s", |
---|
2852 | pw->pw_name, get_canonical_hostname()); |
---|
2853 | |
---|
2854 | if (havecred) |
---|
2855 | try_afscall(setpag); |
---|
2856 | if (!al_local_acct) |
---|
2857 | { |
---|
2858 | status = al_acct_create(pw->pw_name, NULL, getpid(), havecred, 1, |
---|
2859 | &al_warnings); |
---|
2860 | if (status != AL_SUCCESS && status != AL_WARNINGS) |
---|
2861 | packet_disconnect("%s\n", al_strerror(status, &errmem)); |
---|
2862 | } |
---|
2863 | |
---|
2864 | /* al_acct_create may have given us a temp homedir */ |
---|
2865 | pw2 = getpwnam(pw->pw_name); |
---|
2866 | free(pw->pw_dir); |
---|
2867 | pw->pw_dir = xstrdup(pw2->pw_dir); |
---|
2868 | |
---|
2869 | /* The user has been authenticated and accepted. */ |
---|
2870 | packet_start(SSH_SMSG_SUCCESS); |
---|
2871 | packet_send(); |
---|
2872 | packet_write_wait(); |
---|
2873 | |
---|
2874 | /* Perform session preparation. */ |
---|
2875 | do_authenticated(pw); |
---|
2876 | } |
---|
2877 | |
---|
2878 | /* Prepares for an interactive session. This is called after the user has |
---|
2879 | been successfully authenticated. During this message exchange, pseudo |
---|
2880 | terminals are allocated, X11, TCP/IP, and authentication agent forwardings |
---|
2881 | are requested, etc. */ |
---|
2882 | |
---|
2883 | void do_authenticated(struct passwd *pw) |
---|
2884 | { |
---|
2885 | int type; |
---|
2886 | int compression_level = 0, enable_compression_after_reply = 0; |
---|
2887 | int have_pty = 0, ptyfd = -1, ttyfd = -1; |
---|
2888 | int row, col, xpixel, ypixel, screen; |
---|
2889 | unsigned long max_size; |
---|
2890 | char ttyname[64]; |
---|
2891 | char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL; |
---|
2892 | struct group *grp; |
---|
2893 | gid_t tty_gid; |
---|
2894 | mode_t tty_mode; |
---|
2895 | struct stat st; |
---|
2896 | int i; |
---|
2897 | |
---|
2898 | /* Cancel the alarm we set to limit the time taken for authentication. */ |
---|
2899 | alarm(0); |
---|
2900 | |
---|
2901 | /* Inform the channel mechanism that we are the server side and that |
---|
2902 | the client may request to connect to any port at all. (The user could |
---|
2903 | do it anyway, and we wouldn\'t know what is permitted except by the |
---|
2904 | client telling us, so we can equally well trust the client not to request |
---|
2905 | anything bogus.) */ |
---|
2906 | channel_permit_all_opens(); |
---|
2907 | |
---|
2908 | #ifdef F_SECURE_COMMERCIAL |
---|
2909 | |
---|
2910 | |
---|
2911 | |
---|
2912 | |
---|
2913 | |
---|
2914 | |
---|
2915 | |
---|
2916 | |
---|
2917 | #endif /* F_SECURE_COMMERCIAL */ |
---|
2918 | |
---|
2919 | |
---|
2920 | /* We stay in this loop until the client requests to execute a shell or a |
---|
2921 | command. */ |
---|
2922 | while (1) |
---|
2923 | { |
---|
2924 | /* Get a packet from the client. */ |
---|
2925 | type = packet_read(); |
---|
2926 | |
---|
2927 | /* Process the packet. */ |
---|
2928 | switch (type) |
---|
2929 | { |
---|
2930 | case SSH_CMSG_REQUEST_COMPRESSION: |
---|
2931 | compression_level = packet_get_int(); |
---|
2932 | if (compression_level < 1 || compression_level > 9) |
---|
2933 | { |
---|
2934 | packet_send_debug("Received illegal compression level %d.", |
---|
2935 | compression_level); |
---|
2936 | goto fail; |
---|
2937 | } |
---|
2938 | /* Enable compression after we have responded with SUCCESS. */ |
---|
2939 | enable_compression_after_reply = 1; |
---|
2940 | break; |
---|
2941 | |
---|
2942 | case SSH_CMSG_MAX_PACKET_SIZE: |
---|
2943 | /* Get maximum size from paket. */ |
---|
2944 | max_size = packet_get_int(); |
---|
2945 | |
---|
2946 | /* Make sure that it is acceptable. */ |
---|
2947 | if (max_size < 4096 || max_size > 256 * 1024) |
---|
2948 | { |
---|
2949 | packet_send_debug("Received illegal max packet size %lu.", |
---|
2950 | max_size); |
---|
2951 | goto fail; |
---|
2952 | } |
---|
2953 | |
---|
2954 | /* Set the size and return success. */ |
---|
2955 | packet_set_max_size(max_size); |
---|
2956 | break; |
---|
2957 | |
---|
2958 | case SSH_CMSG_REQUEST_PTY: |
---|
2959 | if (no_pty_flag) |
---|
2960 | { |
---|
2961 | packet_get_all(); |
---|
2962 | debug("Allocating a pty not permitted for this authentication."); |
---|
2963 | goto fail; |
---|
2964 | } |
---|
2965 | if (have_pty) |
---|
2966 | packet_disconnect("Protocol error: you already have a pty."); |
---|
2967 | |
---|
2968 | debug("Allocating pty."); |
---|
2969 | |
---|
2970 | /* Allocate a pty and open it. */ |
---|
2971 | if (!pty_allocate(&ptyfd, &ttyfd, ttyname)) |
---|
2972 | { |
---|
2973 | packet_get_all(); |
---|
2974 | error("Failed to allocate pty."); |
---|
2975 | goto fail; |
---|
2976 | } |
---|
2977 | |
---|
2978 | /* Determine the group to make the owner of the tty. */ |
---|
2979 | #ifdef TTY_GROUP |
---|
2980 | grp = getgrnam(TTY_GROUP); |
---|
2981 | #else /* TTY_GROUP */ |
---|
2982 | grp = getgrnam("tty"); |
---|
2983 | #endif /* TTY_GROUP */ |
---|
2984 | if (grp) |
---|
2985 | { |
---|
2986 | tty_gid = grp->gr_gid; |
---|
2987 | tty_mode = S_IRUSR|S_IWUSR|S_IWGRP; |
---|
2988 | } |
---|
2989 | else |
---|
2990 | { |
---|
2991 | tty_gid = pw->pw_gid; |
---|
2992 | tty_mode = S_IRUSR|S_IWUSR|S_IWGRP|S_IWOTH; |
---|
2993 | } |
---|
2994 | |
---|
2995 | /* Change ownership of the tty. */ |
---|
2996 | (void)chown(ttyname, pw->pw_uid, tty_gid); |
---|
2997 | (void)chmod(ttyname, tty_mode); |
---|
2998 | |
---|
2999 | /* Get TERM from the packet. Note that the value may be of arbitrary |
---|
3000 | length. */ |
---|
3001 | term = packet_get_string(NULL); |
---|
3002 | if (strcmp(term, "") == 0) |
---|
3003 | term = NULL; |
---|
3004 | |
---|
3005 | /* Get window size from the packet. */ |
---|
3006 | row = packet_get_int(); |
---|
3007 | col = packet_get_int(); |
---|
3008 | xpixel = packet_get_int(); |
---|
3009 | ypixel = packet_get_int(); |
---|
3010 | pty_change_window_size(ptyfd, row, col, xpixel, ypixel); |
---|
3011 | |
---|
3012 | /* Get tty modes from the packet. */ |
---|
3013 | tty_parse_modes(ttyfd); |
---|
3014 | |
---|
3015 | /* Indicate that we now have a pty. */ |
---|
3016 | have_pty = 1; |
---|
3017 | break; |
---|
3018 | |
---|
3019 | case SSH_CMSG_X11_REQUEST_FORWARDING: |
---|
3020 | #ifdef SSHD_NO_X11_FORWARDING |
---|
3021 | packet_get_all(); |
---|
3022 | debug("X11 forwarding disabled in this site."); |
---|
3023 | packet_send_debug("X11 forwarding disabled in this site."); |
---|
3024 | goto fail; |
---|
3025 | #else |
---|
3026 | if (!options.x11_forwarding) |
---|
3027 | { |
---|
3028 | packet_get_all(); |
---|
3029 | packet_send_debug("X11 forwarding disabled in server configuration file."); |
---|
3030 | goto fail; |
---|
3031 | } |
---|
3032 | #ifdef XAUTH_PATH |
---|
3033 | if (no_x11_forwarding_flag) |
---|
3034 | { |
---|
3035 | packet_get_all(); |
---|
3036 | packet_send_debug("X11 forwarding not permitted for this authentication."); |
---|
3037 | goto fail; |
---|
3038 | } |
---|
3039 | debug("Received request for X11 forwarding with auth spoofing."); |
---|
3040 | if (display) |
---|
3041 | packet_disconnect("Protocol error: X11 display already set."); |
---|
3042 | |
---|
3043 | /* Check whether we have xauth installed on this machine (in case |
---|
3044 | the binary was moved from elsewhere). */ |
---|
3045 | if (stat(options.xauth_path, &st) < 0) |
---|
3046 | { |
---|
3047 | packet_get_all(); |
---|
3048 | packet_send_debug("Remote host has no X11 installed."); |
---|
3049 | goto fail; |
---|
3050 | } |
---|
3051 | |
---|
3052 | /* Process the request. */ |
---|
3053 | proto = packet_get_string(NULL); |
---|
3054 | data = packet_get_string(NULL); |
---|
3055 | if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER || |
---|
3056 | packet_get_len() > 0) |
---|
3057 | screen = packet_get_int(); |
---|
3058 | else |
---|
3059 | screen = 0; |
---|
3060 | display = x11_create_display_inet(screen); |
---|
3061 | if (!display) |
---|
3062 | goto fail; |
---|
3063 | break; |
---|
3064 | #else /* XAUTH_PATH */ |
---|
3065 | /* No xauth program; we won't accept forwarding with spoofing. */ |
---|
3066 | packet_get_all(); |
---|
3067 | packet_send_debug("Client requested X11 forwarding, but the server has no xauth program."); |
---|
3068 | packet_send_debug("This is usually caused by \"xauth\" not being in PATH during compile."); |
---|
3069 | goto fail; |
---|
3070 | #endif /* XAUTH_PATH */ |
---|
3071 | #endif /* SSHD_NO_X11_FORWARDING */ |
---|
3072 | |
---|
3073 | case SSH_CMSG_AGENT_REQUEST_FORWARDING: |
---|
3074 | if (no_agent_forwarding_flag) |
---|
3075 | { |
---|
3076 | packet_get_all(); |
---|
3077 | debug("Authentication agent forwarding not permitted for this authentication."); |
---|
3078 | goto fail; |
---|
3079 | } |
---|
3080 | if (emulation_information & EMULATE_OLD_AGENT_BUG) |
---|
3081 | { |
---|
3082 | debug("Authentication agent forwarding denied because the other end uses too old version."); |
---|
3083 | goto fail; |
---|
3084 | } |
---|
3085 | debug("Received authentication agent forwarding request."); |
---|
3086 | if (!auth_input_request_forwarding(pw)) |
---|
3087 | { |
---|
3088 | goto fail; |
---|
3089 | } |
---|
3090 | break; |
---|
3091 | |
---|
3092 | case SSH_CMSG_PORT_FORWARD_REQUEST: |
---|
3093 | #ifdef SSHD_NO_PORT_FORWARDING |
---|
3094 | packet_get_all(); |
---|
3095 | debug("All port forwardings disabled in this site."); |
---|
3096 | packet_send_debug("All port forwardings disabled in this site."); |
---|
3097 | goto fail; |
---|
3098 | #else |
---|
3099 | if (no_port_forwarding_flag || !options.allow_tcp_forwarding) |
---|
3100 | { |
---|
3101 | packet_get_all(); |
---|
3102 | debug("Port forwarding not permitted for this authentication."); |
---|
3103 | goto fail; |
---|
3104 | } |
---|
3105 | debug("Received TCP/IP port forwarding request."); |
---|
3106 | channel_input_port_forward_request(pw->pw_uid == UID_ROOT); |
---|
3107 | break; |
---|
3108 | #endif |
---|
3109 | |
---|
3110 | case SSH_CMSG_EXEC_SHELL: |
---|
3111 | /* Set interactive/non-interactive mode. */ |
---|
3112 | packet_set_interactive(have_pty || display != NULL, |
---|
3113 | options.keepalives); |
---|
3114 | |
---|
3115 | if (forced_command != NULL) |
---|
3116 | goto do_forced_command; |
---|
3117 | debug("Forking shell."); |
---|
3118 | if (have_pty) |
---|
3119 | do_exec_pty(NULL, ptyfd, ttyfd, ttyname, pw, term, display, proto, |
---|
3120 | data); |
---|
3121 | else |
---|
3122 | do_exec_no_pty(NULL, pw, display, proto, data); |
---|
3123 | return; |
---|
3124 | |
---|
3125 | case SSH_CMSG_EXEC_CMD: |
---|
3126 | /* Set interactive/non-interactive mode. */ |
---|
3127 | packet_set_interactive(have_pty || display != NULL, |
---|
3128 | options.keepalives); |
---|
3129 | |
---|
3130 | /* Get command from the packet. */ |
---|
3131 | command = packet_get_string(NULL); |
---|
3132 | |
---|
3133 | if (forced_command != NULL) |
---|
3134 | { |
---|
3135 | original_command = command; |
---|
3136 | goto do_forced_command; |
---|
3137 | } |
---|
3138 | debug("Executing command '%.500s'", command); |
---|
3139 | if (have_pty) |
---|
3140 | do_exec_pty(command, ptyfd, ttyfd, ttyname, pw, term, display, |
---|
3141 | proto, data); |
---|
3142 | else |
---|
3143 | do_exec_no_pty(command, pw, display, proto, data); |
---|
3144 | xfree(command); |
---|
3145 | return; |
---|
3146 | |
---|
3147 | default: |
---|
3148 | /* Any unknown messages in this phase are ignored, and a failure |
---|
3149 | message is returned. */ |
---|
3150 | packet_get_all(); |
---|
3151 | log_msg("Unknown packet type received after authentication: %d", type); |
---|
3152 | goto fail; |
---|
3153 | } |
---|
3154 | |
---|
3155 | /* The request was successfully processed. */ |
---|
3156 | packet_start(SSH_SMSG_SUCCESS); |
---|
3157 | packet_send(); |
---|
3158 | packet_write_wait(); |
---|
3159 | |
---|
3160 | /* Enable compression now that we have replied if appropriate. */ |
---|
3161 | if (enable_compression_after_reply) |
---|
3162 | { |
---|
3163 | enable_compression_after_reply = 0; |
---|
3164 | packet_start_compression(compression_level); |
---|
3165 | } |
---|
3166 | |
---|
3167 | continue; |
---|
3168 | |
---|
3169 | fail: |
---|
3170 | /* The request failed. */ |
---|
3171 | packet_get_all(); |
---|
3172 | packet_start(SSH_SMSG_FAILURE); |
---|
3173 | packet_send(); |
---|
3174 | packet_write_wait(); |
---|
3175 | continue; |
---|
3176 | |
---|
3177 | do_forced_command: |
---|
3178 | /* There is a forced command specified for this login. Execute it. */ |
---|
3179 | debug("Executing forced command: %.900s", forced_command); |
---|
3180 | if (have_pty) |
---|
3181 | do_exec_pty(forced_command, ptyfd, ttyfd, ttyname, pw, term, display, |
---|
3182 | proto, data); |
---|
3183 | else |
---|
3184 | do_exec_no_pty(forced_command, pw, display, proto, data); |
---|
3185 | return; |
---|
3186 | } |
---|
3187 | } |
---|
3188 | |
---|
3189 | /* This is called to fork and execute a command when we have no tty. This |
---|
3190 | will call do_child from the child, and server_loop from the parent after |
---|
3191 | setting up file descriptors and such. */ |
---|
3192 | |
---|
3193 | void do_exec_no_pty(const char *command, struct passwd *pw, |
---|
3194 | const char *display, const char *auth_proto, |
---|
3195 | const char *auth_data) |
---|
3196 | { |
---|
3197 | int pid; |
---|
3198 | #ifdef USE_PIPES |
---|
3199 | int pin[2], pout[2], perr[2]; |
---|
3200 | #else /* USE_PIPES */ |
---|
3201 | int inout[2], err[2]; |
---|
3202 | #endif /* USE_PIPES */ |
---|
3203 | |
---|
3204 | #ifdef HAVE_OSF1_C2_SECURITY |
---|
3205 | { |
---|
3206 | const char *str; |
---|
3207 | if (str = osf1c2_check_account_and_terminal(pw->pw_name, NULL)) |
---|
3208 | { |
---|
3209 | packet_disconnect(str); |
---|
3210 | } |
---|
3211 | } |
---|
3212 | #endif /* HAVE_OSF1_C2_SECURITY */ |
---|
3213 | #ifdef USE_PIPES |
---|
3214 | /* Allocate pipes for communicating with the program. */ |
---|
3215 | if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0) |
---|
3216 | packet_disconnect("Could not create pipes: %.100s", |
---|
3217 | strerror(errno)); |
---|
3218 | #else /* USE_PIPES */ |
---|
3219 | /* Uses socket pairs to communicate with the program. */ |
---|
3220 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 || |
---|
3221 | socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) |
---|
3222 | packet_disconnect("Could not create socket pairs: %.100s", |
---|
3223 | strerror(errno)); |
---|
3224 | #endif /* USE_PIPES */ |
---|
3225 | |
---|
3226 | /* We no longer need the child running on user's privileges. */ |
---|
3227 | userfile_uninit(); |
---|
3228 | |
---|
3229 | /* Fork the child. */ |
---|
3230 | if ((pid = fork()) == 0) |
---|
3231 | { |
---|
3232 | /* Child. Reinitialize the log since the pid has changed. */ |
---|
3233 | log_init(av0, debug_flag && !inetd_flag, debug_flag, |
---|
3234 | options.quiet_mode, options.log_facility); |
---|
3235 | |
---|
3236 | #ifdef HAVE_SETSID |
---|
3237 | #ifdef ultrix |
---|
3238 | setpgrp(0, 0); |
---|
3239 | #else /* ultrix */ |
---|
3240 | if (setsid() < 0) |
---|
3241 | error("setsid: %.100s", strerror(errno)); |
---|
3242 | #endif |
---|
3243 | #endif /* HAVE_SETSID */ |
---|
3244 | |
---|
3245 | #ifdef USE_PIPES |
---|
3246 | /* Redirect stdin. We close the parent side of the socket pair, |
---|
3247 | and make the child side the standard input. */ |
---|
3248 | close(pin[1]); |
---|
3249 | if (dup2(pin[0], 0) < 0) |
---|
3250 | perror("dup2 stdin"); |
---|
3251 | close(pin[0]); |
---|
3252 | |
---|
3253 | /* Redirect stdout. */ |
---|
3254 | close(pout[0]); |
---|
3255 | if (dup2(pout[1], 1) < 0) |
---|
3256 | perror("dup2 stdout"); |
---|
3257 | close(pout[1]); |
---|
3258 | |
---|
3259 | /* Redirect stderr. */ |
---|
3260 | close(perr[0]); |
---|
3261 | if (dup2(perr[1], 2) < 0) |
---|
3262 | perror("dup2 stderr"); |
---|
3263 | close(perr[1]); |
---|
3264 | #else /* USE_PIPES */ |
---|
3265 | /* Redirect stdin, stdout, and stderr. Stdin and stdout will use the |
---|
3266 | same socket, as some programs (particularly rdist) seem to depend |
---|
3267 | on it. */ |
---|
3268 | close(inout[1]); |
---|
3269 | close(err[1]); |
---|
3270 | if (dup2(inout[0], 0) < 0) /* stdin */ |
---|
3271 | perror("dup2 stdin"); |
---|
3272 | if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */ |
---|
3273 | perror("dup2 stdout"); |
---|
3274 | if (dup2(err[0], 2) < 0) /* stderr */ |
---|
3275 | perror("dup2 stderr"); |
---|
3276 | #endif /* USE_PIPES */ |
---|
3277 | |
---|
3278 | /* Do processing for the child (exec command etc). */ |
---|
3279 | do_child(command, pw, NULL, display, auth_proto, auth_data, NULL); |
---|
3280 | /*NOTREACHED*/ |
---|
3281 | } |
---|
3282 | if (pid < 0) |
---|
3283 | packet_disconnect("fork failed: %.100s", strerror(errno)); |
---|
3284 | #ifdef USE_PIPES |
---|
3285 | /* We are the parent. Close the child sides of the pipes. */ |
---|
3286 | close(pin[0]); |
---|
3287 | close(pout[1]); |
---|
3288 | close(perr[1]); |
---|
3289 | |
---|
3290 | /* Enter the interactive session. Note server_loop will close all |
---|
3291 | filedescriptors. */ |
---|
3292 | server_loop(pid, pin[1], pout[0], perr[0], NULL); |
---|
3293 | /* server_loop has closed pin[1], pout[1], and perr[1]. */ |
---|
3294 | #else /* USE_PIPES */ |
---|
3295 | /* We are the parent. Close the child sides of the socket pairs. */ |
---|
3296 | close(inout[0]); |
---|
3297 | close(err[0]); |
---|
3298 | |
---|
3299 | /* Enter the interactive session. Note: server_loop must be able to handle |
---|
3300 | the case that fdin and fdout are the same. */ |
---|
3301 | server_loop(pid, inout[1], inout[1], err[1], NULL); |
---|
3302 | /* server_loop has closed inout[1] and err[1]. */ |
---|
3303 | #endif /* USE_PIPES */ |
---|
3304 | } |
---|
3305 | |
---|
3306 | struct pty_cleanup_context |
---|
3307 | { |
---|
3308 | const char *ttyname; |
---|
3309 | int pid; |
---|
3310 | int alread_cleaned; |
---|
3311 | }; |
---|
3312 | |
---|
3313 | /* Function to perform cleanup if we get aborted abnormally (e.g., due to a |
---|
3314 | dropped connection). */ |
---|
3315 | |
---|
3316 | void pty_cleanup_proc(void *context) |
---|
3317 | { |
---|
3318 | struct pty_cleanup_context *cu = context; |
---|
3319 | |
---|
3320 | if (cu->alread_cleaned) |
---|
3321 | { |
---|
3322 | debug("pty_cleanup_proc called again, ignored"); |
---|
3323 | } |
---|
3324 | else |
---|
3325 | { |
---|
3326 | debug("pty_cleanup_proc called"); |
---|
3327 | |
---|
3328 | /* Record that the user has logged out. */ |
---|
3329 | record_logout(cu->pid, cu->ttyname); |
---|
3330 | |
---|
3331 | /* Release the pseudo-tty. */ |
---|
3332 | pty_release(cu->ttyname); |
---|
3333 | |
---|
3334 | cu->alread_cleaned = 1; |
---|
3335 | } |
---|
3336 | } |
---|
3337 | |
---|
3338 | /* This is called to fork and execute a command when we have a tty. This |
---|
3339 | will call do_child from the child, and server_loop from the parent after |
---|
3340 | setting up file descriptors, controlling tty, updating wtmp, utmp, |
---|
3341 | lastlog, and other such operations. */ |
---|
3342 | |
---|
3343 | void do_exec_pty(const char *command, int ptyfd, int ttyfd, |
---|
3344 | const char *ttyname, struct passwd *pw, const char *term, |
---|
3345 | const char *display, const char *auth_proto, |
---|
3346 | const char *auth_data) |
---|
3347 | { |
---|
3348 | int pid, fdout; |
---|
3349 | const char *hostname; |
---|
3350 | time_t last_login_time = 0; |
---|
3351 | char buf[100], *time_string; |
---|
3352 | char line[256]; |
---|
3353 | struct stat st; |
---|
3354 | int quiet_login; |
---|
3355 | struct sockaddr_in from; |
---|
3356 | int fromlen; |
---|
3357 | struct pty_cleanup_context cleanup_context; |
---|
3358 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
3359 | login_cap_t *lc; |
---|
3360 | #endif |
---|
3361 | #if defined (__bsdi__) && _BSDI_VERSION >= 199510 |
---|
3362 | struct timeval tp; |
---|
3363 | #endif /* __bsdi__ && _BSDI_VERSION >= 199510 */ |
---|
3364 | |
---|
3365 | #ifdef HAVE_OSF1_C2_SECURITY |
---|
3366 | { |
---|
3367 | const char *str; |
---|
3368 | if (str = osf1c2_check_account_and_terminal(pw->pw_name, ttyname)) |
---|
3369 | { |
---|
3370 | packet_disconnect(str); |
---|
3371 | } |
---|
3372 | } |
---|
3373 | #endif /* HAVE_OSF1_C2_SECURITY */ |
---|
3374 | |
---|
3375 | /* We no longer need the child running on user's privileges. */ |
---|
3376 | userfile_uninit(); |
---|
3377 | |
---|
3378 | /* Get remote host name. */ |
---|
3379 | hostname = get_canonical_hostname(); |
---|
3380 | |
---|
3381 | /* Get the time when the user last logged in. Buf will be set to contain |
---|
3382 | the hostname the last login was from. */ |
---|
3383 | #ifndef USELOGIN |
---|
3384 | options.use_login = 0; |
---|
3385 | #endif /* USELOGIN */ |
---|
3386 | if (!options.use_login) |
---|
3387 | last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, |
---|
3388 | buf, sizeof(buf)); |
---|
3389 | |
---|
3390 | /* Fork the child. */ |
---|
3391 | if ((pid = fork()) == 0) |
---|
3392 | { |
---|
3393 | pid = getpid(); |
---|
3394 | |
---|
3395 | /* Child. Reinitialize the log because the pid has changed. */ |
---|
3396 | log_init(av0, debug_flag && !inetd_flag, debug_flag, options.quiet_mode, |
---|
3397 | options.log_facility); |
---|
3398 | |
---|
3399 | #ifdef HAVE_SETSID |
---|
3400 | #ifdef ultrix |
---|
3401 | setpgrp(0, 0); |
---|
3402 | #else /* ultrix */ |
---|
3403 | if (setsid() < 0) |
---|
3404 | error("setsid: %.100s", strerror(errno)); |
---|
3405 | #endif |
---|
3406 | #endif /* HAVE_SETSID */ |
---|
3407 | |
---|
3408 | /* Close the master side of the pseudo tty. */ |
---|
3409 | close(ptyfd); |
---|
3410 | |
---|
3411 | /* Make the pseudo tty our controlling tty. */ |
---|
3412 | pty_make_controlling_tty(&ttyfd, ttyname); |
---|
3413 | |
---|
3414 | /* Redirect stdin from the pseudo tty. */ |
---|
3415 | if (dup2(ttyfd, fileno(stdin)) < 0) |
---|
3416 | error("dup2 stdin failed: %.100s", strerror(errno)); |
---|
3417 | |
---|
3418 | /* Redirect stdout to the pseudo tty. */ |
---|
3419 | if (dup2(ttyfd, fileno(stdout)) < 0) |
---|
3420 | error("dup2 stdin failed: %.100s", strerror(errno)); |
---|
3421 | |
---|
3422 | /* Redirect stderr to the pseudo tty. */ |
---|
3423 | if (dup2(ttyfd, fileno(stderr)) < 0) |
---|
3424 | error("dup2 stdin failed: %.100s", strerror(errno)); |
---|
3425 | |
---|
3426 | /* Close the extra descriptor for the pseudo tty. */ |
---|
3427 | close(ttyfd); |
---|
3428 | |
---|
3429 | /* Get IP address of client. This is needed because we want to record |
---|
3430 | where the user logged in from. If the connection is not a socket, |
---|
3431 | let the ip address be 0.0.0.0. */ |
---|
3432 | memset(&from, 0, sizeof(from)); |
---|
3433 | if (packet_get_connection_in() == packet_get_connection_out()) |
---|
3434 | { |
---|
3435 | fromlen = sizeof(from); |
---|
3436 | if (getpeername(packet_get_connection_in(), |
---|
3437 | (struct sockaddr *)&from, &fromlen) < 0) |
---|
3438 | fatal("getpeername: %.100s", strerror(errno)); |
---|
3439 | } |
---|
3440 | |
---|
3441 | /* Record that there was a login on that terminal. */ |
---|
3442 | record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname, |
---|
3443 | &from); |
---|
3444 | |
---|
3445 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
3446 | lc = login_getclass(pw->pw_class); |
---|
3447 | #endif |
---|
3448 | |
---|
3449 | /* Check if .hushlogin exists. Note that we cannot use userfile |
---|
3450 | here because we are in the child. */ |
---|
3451 | sprintf(line, "%.200s/.hushlogin", pw->pw_dir); |
---|
3452 | quiet_login = stat(line, &st) >= 0; |
---|
3453 | |
---|
3454 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
3455 | quiet_login = login_getcapbool(lc, "hushlogin", quiet_login); |
---|
3456 | #endif |
---|
3457 | |
---|
3458 | /* If the user has logged in before, display the time of last login. |
---|
3459 | However, don't display anything extra if a command has been |
---|
3460 | specified (so that ssh can be used to execute commands on a remote |
---|
3461 | machine without users knowing they are going to another machine). */ |
---|
3462 | if (!options.use_login && command == NULL && last_login_time != 0 && |
---|
3463 | !quiet_login) |
---|
3464 | { |
---|
3465 | /* Convert the date to a string. */ |
---|
3466 | time_string = ctime(&last_login_time); |
---|
3467 | /* Remove the trailing newline. */ |
---|
3468 | if (strchr(time_string, '\n')) |
---|
3469 | *strchr(time_string, '\n') = 0; |
---|
3470 | /* Display the last login time. Host if displayed if known. */ |
---|
3471 | if (strcmp(buf, "") == 0) |
---|
3472 | printf("Last login: %s\r\n", time_string); |
---|
3473 | else |
---|
3474 | printf("Last login: %s from %s\r\n", time_string, buf); |
---|
3475 | } |
---|
3476 | |
---|
3477 | #ifdef __FreeBSD__ |
---|
3478 | if (command == NULL && !quiet_login) |
---|
3479 | { |
---|
3480 | #ifdef HAVE_LOGIN_CAP_H |
---|
3481 | char *cw; |
---|
3482 | FILE *f; |
---|
3483 | |
---|
3484 | cw = login_getcapstr(lc, "copyright", NULL, NULL); |
---|
3485 | if (cw != NULL && (f = fopen(cw, "r")) != NULL) |
---|
3486 | { |
---|
3487 | while (fgets(line, sizeof(line), f)) |
---|
3488 | fputs(line, stdout); |
---|
3489 | fclose(f); |
---|
3490 | } |
---|
3491 | else |
---|
3492 | #endif |
---|
3493 | printf("%s\n\t%s %s\n\n", |
---|
3494 | "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994", |
---|
3495 | "The Regents of the University of California. ", |
---|
3496 | "All rights reserved."); |
---|
3497 | } |
---|
3498 | #endif |
---|
3499 | |
---|
3500 | /* Print /etc/motd unless a command was specified or printing it was |
---|
3501 | disabled in server options. Note that some machines appear to |
---|
3502 | print it in /etc/profile or similar. */ |
---|
3503 | if (!options.use_login && command == NULL && options.print_motd && |
---|
3504 | !quiet_login) |
---|
3505 | { |
---|
3506 | FILE *f; |
---|
3507 | |
---|
3508 | /* Print /etc/motd if it exists. */ |
---|
3509 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
3510 | f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", "/etc/motd"), |
---|
3511 | "r"); |
---|
3512 | #else |
---|
3513 | f = fopen("/etc/motd", "r"); |
---|
3514 | #endif |
---|
3515 | if (f) |
---|
3516 | { |
---|
3517 | while (fgets(line, sizeof(line), f)) |
---|
3518 | fputs(line, stdout); |
---|
3519 | fclose(f); |
---|
3520 | } |
---|
3521 | #if defined (__bsdi__) && _BSDI_VERSION >= 199510 |
---|
3522 | if (pw->pw_change || pw->pw_expire) |
---|
3523 | (void)gettimeofday(&tp, (struct timezone *)NULL); |
---|
3524 | if (pw->pw_change) |
---|
3525 | { |
---|
3526 | if (tp.tv_sec >= pw->pw_change) |
---|
3527 | { |
---|
3528 | fprintf(stderr,"Sorry -- your password has expired.\n"); |
---|
3529 | exit(254); |
---|
3530 | } |
---|
3531 | days_before_password_expires = (pw->pw_change - tp.tv_sec) / |
---|
3532 | 86400; |
---|
3533 | } |
---|
3534 | if (pw->pw_expire) |
---|
3535 | { |
---|
3536 | if (tp.tv_sec >= pw->pw_expire) |
---|
3537 | { |
---|
3538 | fprintf(stderr,"Sorry -- your account has expired.\n"); |
---|
3539 | exit(254); |
---|
3540 | } |
---|
3541 | days_before_account_expires = (pw->pw_expire - tp.tv_sec) / |
---|
3542 | 86400; |
---|
3543 | } |
---|
3544 | #endif /* __bsdi__ & _BSDI_VERSION >= 199510 */ |
---|
3545 | } |
---|
3546 | |
---|
3547 | #if defined (__FreeBSD__) && defined HAVE_LOGIN_CAP_H |
---|
3548 | login_close(lc); |
---|
3549 | #endif |
---|
3550 | |
---|
3551 | /* Do common processing for the child, such as execing the command. */ |
---|
3552 | do_child(command, pw, term, display, auth_proto, auth_data, ttyname); |
---|
3553 | /*NOTREACHED*/ |
---|
3554 | } |
---|
3555 | if (pid < 0) |
---|
3556 | packet_disconnect("fork failed: %.100s", strerror(errno)); |
---|
3557 | /* Parent. Close the slave side of the pseudo tty. */ |
---|
3558 | close(ttyfd); |
---|
3559 | |
---|
3560 | #ifdef ultrix /* corey */ |
---|
3561 | setpgrp(0,0); /* disconnect from child's process group */ |
---|
3562 | #endif /* ultrix */ |
---|
3563 | |
---|
3564 | /* Create another descriptor of the pty master side for use as the standard |
---|
3565 | input. We could use the original descriptor, but this simplifies code |
---|
3566 | in server_loop. The descriptor is bidirectional. */ |
---|
3567 | fdout = dup(ptyfd); |
---|
3568 | if (fdout < 0) |
---|
3569 | packet_disconnect("dup failed: %.100s", strerror(errno)); |
---|
3570 | |
---|
3571 | /* Add a cleanup function to clear the utmp entry and record logout time |
---|
3572 | in case we call fatal() (e.g., the connection gets closed). */ |
---|
3573 | cleanup_context.pid = pid; |
---|
3574 | cleanup_context.ttyname = ttyname; |
---|
3575 | cleanup_context.alread_cleaned = 0; |
---|
3576 | fatal_add_cleanup(pty_cleanup_proc, (void *)&cleanup_context); |
---|
3577 | |
---|
3578 | /* Enter interactive session, . */ |
---|
3579 | server_loop(pid, ptyfd, fdout, -1, &cleanup_context); |
---|
3580 | /* server_loop has closed ptyfd and fdout. */ |
---|
3581 | /* server_loop has already Released the pseudo-tty. */ |
---|
3582 | |
---|
3583 | /* Cancel the cleanup function. */ |
---|
3584 | fatal_remove_cleanup(pty_cleanup_proc, (void *)&cleanup_context); |
---|
3585 | |
---|
3586 | /* Record that the user has logged out. */ |
---|
3587 | record_logout(pid, ttyname); |
---|
3588 | } |
---|
3589 | |
---|
3590 | /* Sets the value of the given variable in the environment. If the variable |
---|
3591 | already exists, its value is overriden. */ |
---|
3592 | |
---|
3593 | void child_set_env(char ***envp, unsigned int *envsizep, const char *name, |
---|
3594 | const char *value) |
---|
3595 | { |
---|
3596 | unsigned int i, namelen; |
---|
3597 | char **env; |
---|
3598 | |
---|
3599 | /* Find the slot where the value should be stored. If the variable already |
---|
3600 | exists, we reuse the slot; otherwise we append a new slot at the end |
---|
3601 | of the array, expanding if necessary. */ |
---|
3602 | env = *envp; |
---|
3603 | namelen = strlen(name); |
---|
3604 | for (i = 0; env[i]; i++) |
---|
3605 | if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') |
---|
3606 | break; |
---|
3607 | if (env[i]) |
---|
3608 | { |
---|
3609 | /* Name already exists. Reuse the slot. */ |
---|
3610 | xfree(env[i]); |
---|
3611 | } |
---|
3612 | else |
---|
3613 | { |
---|
3614 | /* New variable. Expand the array if necessary. */ |
---|
3615 | if (i >= (*envsizep) - 1) |
---|
3616 | { |
---|
3617 | (*envsizep) += 50; |
---|
3618 | env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *)); |
---|
3619 | } |
---|
3620 | |
---|
3621 | /* Need to set the NULL pointer at end of array beyond the new |
---|
3622 | slot. */ |
---|
3623 | env[i + 1] = NULL; |
---|
3624 | } |
---|
3625 | |
---|
3626 | /* Allocate space and format the variable in the appropriate slot. */ |
---|
3627 | env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); |
---|
3628 | sprintf(env[i], "%s=%s", name, value); |
---|
3629 | } |
---|
3630 | |
---|
3631 | /* Reads environment variables from the given file and adds/overrides them |
---|
3632 | into the environment. If the file does not exist, this does nothing. |
---|
3633 | Otherwise, it must consist of empty lines, comments (line starts with '#') |
---|
3634 | and assignments of the form name=value. No other forms are allowed. */ |
---|
3635 | |
---|
3636 | void read_environment_file(char ***env, unsigned int *envsize, |
---|
3637 | const char *filename) |
---|
3638 | { |
---|
3639 | FILE *f; |
---|
3640 | char buf[4096]; |
---|
3641 | char *cp, *value; |
---|
3642 | |
---|
3643 | /* Open the environment file. Note that this is only called on the user's |
---|
3644 | uid, and thus should not cause security problems. */ |
---|
3645 | f = fopen(filename, "r"); |
---|
3646 | if (!f) |
---|
3647 | return; /* Not found. */ |
---|
3648 | |
---|
3649 | /* Process each line. */ |
---|
3650 | while (fgets(buf, sizeof(buf), f)) |
---|
3651 | { |
---|
3652 | /* Skip leading whitespace. */ |
---|
3653 | for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) |
---|
3654 | ; |
---|
3655 | |
---|
3656 | /* Ignore empty and comment lines. */ |
---|
3657 | if (!*cp || *cp == '#' || *cp == '\n') |
---|
3658 | continue; |
---|
3659 | |
---|
3660 | /* Remove newline. */ |
---|
3661 | if (strchr(cp, '\n')) |
---|
3662 | *strchr(cp, '\n') = '\0'; |
---|
3663 | |
---|
3664 | /* Find the equals sign. Its lack indicates badly formatted line. */ |
---|
3665 | value = strchr(cp, '='); |
---|
3666 | if (value == NULL) |
---|
3667 | { |
---|
3668 | fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); |
---|
3669 | continue; |
---|
3670 | } |
---|
3671 | |
---|
3672 | /* Replace the equals sign by nul, and advance value to the value |
---|
3673 | string. */ |
---|
3674 | *value = '\0'; |
---|
3675 | value++; |
---|
3676 | |
---|
3677 | /* Set the value in environment. */ |
---|
3678 | child_set_env(env, envsize, cp, value); |
---|
3679 | } |
---|
3680 | |
---|
3681 | fclose(f); |
---|
3682 | } |
---|
3683 | |
---|
3684 | |
---|
3685 | #ifdef HAVE_ETC_DEFAULT_LOGIN |
---|
3686 | |
---|
3687 | /* Gets the value of the given variable in the environment. If the |
---|
3688 | variable does not exist, returns NULL. */ |
---|
3689 | |
---|
3690 | char *child_get_env(char **env, const char *name) |
---|
3691 | { |
---|
3692 | unsigned int i, namelen; |
---|
3693 | |
---|
3694 | namelen = strlen(name); |
---|
3695 | |
---|
3696 | for (i = 0; env[i]; i++) |
---|
3697 | if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') |
---|
3698 | break; |
---|
3699 | if (env[i]) |
---|
3700 | return &env[i][namelen + 1]; |
---|
3701 | else |
---|
3702 | return NULL; |
---|
3703 | } |
---|
3704 | |
---|
3705 | /* Processes /etc/default/login; this involves things like environment |
---|
3706 | settings, ulimit, etc. This file exists at least on Solaris 2.x. */ |
---|
3707 | |
---|
3708 | void read_etc_default_login(char ***env, unsigned int *envsize, |
---|
3709 | const char *user_shell, uid_t user_uid) |
---|
3710 | { |
---|
3711 | unsigned int defenvsize; |
---|
3712 | char **defenv, *def; |
---|
3713 | int i; |
---|
3714 | |
---|
3715 | /* Read /etc/default/login into a separate temporary environment. */ |
---|
3716 | defenvsize = 10; |
---|
3717 | defenv = xmalloc(defenvsize * sizeof(char *)); |
---|
3718 | defenv[0] = NULL; |
---|
3719 | read_environment_file(&defenv, &defenvsize, "/etc/default/login"); |
---|
3720 | |
---|
3721 | /* Set SHELL if ALTSHELL is YES. */ |
---|
3722 | def = child_get_env(defenv, "ALTSHELL"); |
---|
3723 | if (def != NULL && strcmp(def, "YES") == 0) |
---|
3724 | child_set_env(env, envsize, "SHELL", user_shell); |
---|
3725 | |
---|
3726 | /* Set PATH from SUPATH if we are logging in as root, and PATH |
---|
3727 | otherwise. If neither of these exists, we use the default ssh |
---|
3728 | path. */ |
---|
3729 | if (user_uid == UID_ROOT) |
---|
3730 | def = child_get_env(defenv, "SUPATH"); |
---|
3731 | else |
---|
3732 | def = child_get_env(defenv, "PATH"); |
---|
3733 | if (def != NULL) |
---|
3734 | { |
---|
3735 | char *newpath; |
---|
3736 | newpath = xmalloc(strlen(def) + sizeof(SSH_BINDIR) + 1); |
---|
3737 | sprintf(newpath, "%s:%s", def, SSH_BINDIR); |
---|
3738 | child_set_env(env, envsize, "PATH", newpath); |
---|
3739 | xfree(newpath); |
---|
3740 | } |
---|
3741 | else |
---|
3742 | child_set_env(env, envsize, "PATH", DEFAULT_PATH ":" SSH_BINDIR); |
---|
3743 | |
---|
3744 | /* Set TZ if TIMEZONE is defined and we haven't inherited a value |
---|
3745 | for TZ. */ |
---|
3746 | def = getenv("TZ"); |
---|
3747 | if (def == NULL) |
---|
3748 | def = child_get_env(defenv, "TIMEZONE"); |
---|
3749 | if (def != NULL) |
---|
3750 | child_set_env(env, envsize, "TZ", def); |
---|
3751 | |
---|
3752 | /* Set HZ if defined. */ |
---|
3753 | def = child_get_env(defenv, "HZ"); |
---|
3754 | if (def != NULL) |
---|
3755 | child_set_env(env, envsize, "HZ", def); |
---|
3756 | |
---|
3757 | /* Set up the default umask if UMASK is defined. */ |
---|
3758 | def = child_get_env(defenv, "UMASK"); |
---|
3759 | if (def != NULL) |
---|
3760 | { |
---|
3761 | int i, value; |
---|
3762 | |
---|
3763 | for (value = i = 0; |
---|
3764 | def[i] && isdigit(def[i]) && def[i] != '8' && def[i] != '9'; |
---|
3765 | i++) |
---|
3766 | value = value * 8 + def[i] - '0'; |
---|
3767 | |
---|
3768 | umask(value); |
---|
3769 | } |
---|
3770 | |
---|
3771 | /* Set up the file size ulimit if ULIMIT is set. */ |
---|
3772 | def = child_get_env(defenv, "ULIMIT"); |
---|
3773 | if (def != NULL && atoi(def) > 0) |
---|
3774 | ulimit(UL_SETFSIZE, atoi(def)); |
---|
3775 | |
---|
3776 | /* Free the temporary environment. */ |
---|
3777 | for (i = 0; defenv[i]; i++) |
---|
3778 | xfree(defenv[i]); |
---|
3779 | xfree(defenv); |
---|
3780 | } |
---|
3781 | |
---|
3782 | #endif /* HAVE_ETC_DEFAULT_LOGIN */ |
---|
3783 | |
---|
3784 | #if defined(NOLOGIN_ALLOW) |
---|
3785 | /* If /etc/nologin is in place, check this file for users to allow anyway. |
---|
3786 | Useful for sys-admins to be able to touch nologin and still get in to do |
---|
3787 | remote maintainence. */ |
---|
3788 | int ignore_nologin(char *username) |
---|
3789 | { |
---|
3790 | FILE *ignore_file; |
---|
3791 | char buf[256], *begin, *end; |
---|
3792 | int length; |
---|
3793 | |
---|
3794 | ignore_file = fopen(NOLOGIN_ALLOW, "r"); |
---|
3795 | if (ignore_file == NULL) |
---|
3796 | return 0; |
---|
3797 | |
---|
3798 | while (fgets(buf, 256, ignore_file) != NULL) |
---|
3799 | { |
---|
3800 | if ((end = strpbrk(buf, "# \r\t\n")) != NULL) |
---|
3801 | *end='\0'; |
---|
3802 | begin = strpbrk(buf, "abcdefghijklmnopqrstuvwxyz0123456789"); |
---|
3803 | if (begin == NULL) |
---|
3804 | continue; |
---|
3805 | length = strspn(begin, "abcdefghijklmnopqrstuvwxyz0123456789-_"); |
---|
3806 | if (length > 8) |
---|
3807 | continue; |
---|
3808 | begin[length] = '\0'; |
---|
3809 | if (!strcmp(begin, username)) |
---|
3810 | { |
---|
3811 | fprintf(stderr,"\nWARNING: /etc/nologin is in place.\n\n"); |
---|
3812 | fclose(ignore_file); |
---|
3813 | return(1); |
---|
3814 | } |
---|
3815 | } |
---|
3816 | fclose(ignore_file); |
---|
3817 | return 0; |
---|
3818 | } |
---|
3819 | #endif /* NOLOGIN_ALLOW */ |
---|
3820 | |
---|
3821 | #ifdef HAVE_SGI_PROJ_H |
---|
3822 | /* |
---|
3823 | On a SGI, set the account number for the current process to the user's |
---|
3824 | default account. If this is not done, the process will have an account |
---|
3825 | of zero and accounting will not operate correctly. |
---|
3826 | |
---|
3827 | Eivind Gjelseth |
---|
3828 | Para//ab, High Performance Computing Centre |
---|
3829 | eivind@ii.uib.no |
---|
3830 | |
---|
3831 | */ |
---|
3832 | int sgi_project_setup(char *username) |
---|
3833 | { |
---|
3834 | int err; |
---|
3835 | int naccts; |
---|
3836 | projid_t pbuf; |
---|
3837 | |
---|
3838 | /* Find default project for a particular user */ |
---|
3839 | if ((naccts = getprojuser(username, &pbuf, 1)) < 0) |
---|
3840 | { |
---|
3841 | debug("System call getprojuser failed"); |
---|
3842 | return(-1); |
---|
3843 | } |
---|
3844 | |
---|
3845 | /* Create a new array session and moves the current |
---|
3846 | process from its original array session to the new one. */ |
---|
3847 | if (newarraysess() < 0) |
---|
3848 | { |
---|
3849 | debug("System call newarraysess failure"); |
---|
3850 | return(-1); |
---|
3851 | } |
---|
3852 | |
---|
3853 | /* Change the project ID for the array session. */ |
---|
3854 | /* Must be changed after the new array session has been created. */ |
---|
3855 | if (naccts) |
---|
3856 | err = setprid(pbuf.proj_id); |
---|
3857 | |
---|
3858 | if (err != 0) |
---|
3859 | { |
---|
3860 | debug("System call setprid failure"); |
---|
3861 | return(-1); |
---|
3862 | } |
---|
3863 | |
---|
3864 | return(0); |
---|
3865 | } |
---|
3866 | #endif /* HAVE_SGI_PROJ_H */ |
---|
3867 | |
---|
3868 | /* Performs common processing for the child, such as setting up the |
---|
3869 | environment, closing extra file descriptors, setting the user and group |
---|
3870 | ids, and executing the command or shell. */ |
---|
3871 | |
---|
3872 | void do_child(const char *command, struct passwd *pw, const char *term, |
---|
3873 | const char *display, const char *auth_proto, |
---|
3874 | const char *auth_data, const char *ttyname) |
---|
3875 | { |
---|
3876 | const char *shell, *cp; |
---|
3877 | char buf[256]; |
---|
3878 | FILE *f; |
---|
3879 | unsigned int envsize, i; |
---|
3880 | char **env; |
---|
3881 | extern char **environ; |
---|
3882 | struct stat st; |
---|
3883 | char *argv[10]; |
---|
3884 | uid_t user_uid; |
---|
3885 | gid_t user_gid; |
---|
3886 | char *user_dir; |
---|
3887 | char *user_name; |
---|
3888 | char *user_shell; |
---|
3889 | char *remote_ip; |
---|
3890 | int remote_port; |
---|
3891 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
3892 | login_cap_t *lc; |
---|
3893 | char *real_shell; |
---|
3894 | |
---|
3895 | lc = login_getclass(pw->pw_class); |
---|
3896 | auth_checknologin(lc); |
---|
3897 | #else /* !HAVE_LOGIN_CAP_H */ |
---|
3898 | #if defined (__bsdi__) && _BSDI_VERSION > 199510 |
---|
3899 | login_cap_t *lc = 0; |
---|
3900 | |
---|
3901 | if ((lc = login_getclass(pw->pw_class)) == NULL) |
---|
3902 | { |
---|
3903 | log_msg("User class %.100s for %.100s not found, assuming default", |
---|
3904 | pw->pw_class, pw->pw_name); |
---|
3905 | lc = login_getclass("default") ; |
---|
3906 | } |
---|
3907 | #else /* __bsdi__ && _BSDI_VERSION >= 199510 */ |
---|
3908 | #if defined (__bsdi__) && _BSDI_VERSION == 199510 |
---|
3909 | login_cap_t *lc = 0; |
---|
3910 | |
---|
3911 | if ((lc = login_getclass(pw)) == NULL) |
---|
3912 | { |
---|
3913 | log_msg("User class %.100s for %.100s not found, assuming default", |
---|
3914 | pw->pw_class, pw->pw_name); |
---|
3915 | pw->pw_class = "default"; |
---|
3916 | lc = login_getclass(pw) ; |
---|
3917 | } |
---|
3918 | #endif /* defined (__bsdi__) && _BSDI_VERSION == 199510 */ |
---|
3919 | #endif /* __bsdi__ && _BSDI_VERSION >= 199510 */ |
---|
3920 | |
---|
3921 | /* Print any leftover libal warnings */ |
---|
3922 | if (al_warnings) |
---|
3923 | { |
---|
3924 | int i; |
---|
3925 | char *errmem; |
---|
3926 | |
---|
3927 | for (i = 0; al_warnings[i]; i++) |
---|
3928 | { |
---|
3929 | fprintf(stderr, "Warning: %s\n", |
---|
3930 | al_strerror(al_warnings[i], &errmem)); |
---|
3931 | al_free_errmem(errmem); |
---|
3932 | } |
---|
3933 | free(al_warnings); |
---|
3934 | } |
---|
3935 | |
---|
3936 | /* Check /etc/nologin. */ |
---|
3937 | f = fopen("/etc/nologin", "r"); |
---|
3938 | if (f) |
---|
3939 | { /* /etc/nologin exists. Print its contents and exit. */ |
---|
3940 | /* Print a message about /etc/nologin existing; I am getting |
---|
3941 | questions because of this every week. */ |
---|
3942 | #if defined(NOLOGIN_ALLOW) |
---|
3943 | if (pw->pw_name && ignore_nologin(pw->pw_name)) |
---|
3944 | { |
---|
3945 | fclose(f); |
---|
3946 | } else { |
---|
3947 | #endif |
---|
3948 | fprintf(stderr, "Logins are currently denied by /etc/nologin:\n"); |
---|
3949 | while (fgets(buf, sizeof(buf), f)) |
---|
3950 | fputs(buf, stderr); |
---|
3951 | fclose(f); |
---|
3952 | #if defined (__bsdi__) && _BSDI_VERSION >= 199510 |
---|
3953 | if (pw->pw_uid != UID_ROOT && |
---|
3954 | !login_getcapbool(lc, "ignorenologin", 0)) |
---|
3955 | exit(254); |
---|
3956 | #else |
---|
3957 | if (pw->pw_uid != UID_ROOT) |
---|
3958 | exit(254); |
---|
3959 | #endif /* __bsdi__ && _BSDI_VERSION >= 199510 */ |
---|
3960 | #if defined(NOLOGIN_ALLOW) |
---|
3961 | } |
---|
3962 | #endif |
---|
3963 | } |
---|
3964 | #endif /* HAVE_LOGIN_CAP_H */ |
---|
3965 | |
---|
3966 | if (command != NULL) |
---|
3967 | { |
---|
3968 | /* If executing a command as root, log the whole command. For normal |
---|
3969 | users, don't log the command, because logging it would be a |
---|
3970 | violation of the user's privacy (and even potentially illegal with |
---|
3971 | respect to privacy/data protection laws in some countries). */ |
---|
3972 | if (pw->pw_uid == UID_ROOT) |
---|
3973 | log_msg("executing remote command as root: %.200s", command); |
---|
3974 | else |
---|
3975 | log_msg("executing remote command as user %.200s", pw->pw_name); |
---|
3976 | } |
---|
3977 | |
---|
3978 | #ifndef HAVE_LOGIN_CAP_H |
---|
3979 | #ifdef HAVE_SETLOGIN |
---|
3980 | /* Set login name in the kernel. Warning: setsid() must be called before |
---|
3981 | this. */ |
---|
3982 | #ifdef USELOGIN |
---|
3983 | if (command != NULL || !options.use_login) |
---|
3984 | if (setlogin(pw->pw_name) < 0) |
---|
3985 | error("setlogin failed: %.100s", strerror(errno)); |
---|
3986 | #else /* USELOGIN */ |
---|
3987 | if (setlogin(pw->pw_name) < 0) |
---|
3988 | error("setlogin failed: %.100s", strerror(errno)); |
---|
3989 | #endif /* USELOGIN */ |
---|
3990 | #endif /* HAVE_SETLOGIN */ |
---|
3991 | |
---|
3992 | #ifdef HAVE_USERSEC_H |
---|
3993 | /* On AIX, this "sets process credentials". I am not sure what this |
---|
3994 | includes, but it seems to be important. This also does setuid |
---|
3995 | (but we do it below as well just in case). */ |
---|
3996 | if (setpcred((char *)pw->pw_name, NULL)) |
---|
3997 | log_msg("setpcred %.100s: %.100s", strerror(errno)); |
---|
3998 | #endif /* HAVE_USERSEC_H */ |
---|
3999 | #endif /* !HAVE_LOGIN_CAP_H */ |
---|
4000 | |
---|
4001 | /* Save some data that will be needed so that we can do certain cleanups |
---|
4002 | before we switch to user's uid. (We must clear all sensitive data |
---|
4003 | and access rights from memory before doing that.) */ |
---|
4004 | user_uid = pw->pw_uid; |
---|
4005 | user_gid = pw->pw_gid; |
---|
4006 | user_dir = xstrdup(pw->pw_dir); |
---|
4007 | user_name = xstrdup(pw->pw_name); |
---|
4008 | user_shell = xstrdup(pw->pw_shell); |
---|
4009 | remote_ip = xstrdup(get_remote_ipaddr()); |
---|
4010 | remote_port = get_remote_port(); |
---|
4011 | |
---|
4012 | /* Close the connection descriptors; note that this is the child, and the |
---|
4013 | server will still have the socket open, and it is important that we |
---|
4014 | do not shutdown it. Note that the descriptors cannot be closed before |
---|
4015 | building the environment, as we call get_remote_ipaddr there. */ |
---|
4016 | if (packet_get_connection_in() == packet_get_connection_out()) |
---|
4017 | close(packet_get_connection_in()); |
---|
4018 | else |
---|
4019 | { |
---|
4020 | close(packet_get_connection_in()); |
---|
4021 | close(packet_get_connection_out()); |
---|
4022 | } |
---|
4023 | /* Close all descriptors related to channels. They will still remain |
---|
4024 | open in the parent. */ |
---|
4025 | channel_close_all(); |
---|
4026 | |
---|
4027 | /* Close any extra file descriptors. Note that there may still be |
---|
4028 | descriptors left by system functions. They will be closed later. */ |
---|
4029 | endpwent(); |
---|
4030 | endhostent(); |
---|
4031 | |
---|
4032 | /* Set dummy encryption key to clear information about the key from |
---|
4033 | memory. This key will never be used. */ |
---|
4034 | packet_set_encryption_key((void *)"0123456789ABCDEF0123456789ABCDEF", 32, |
---|
4035 | SSH_CIPHER_3DES, 0); |
---|
4036 | |
---|
4037 | /* Clear any remaining data in the random number generator. */ |
---|
4038 | random_clear(&sensitive_data.random_state); |
---|
4039 | |
---|
4040 | /* The sensitive private keys were cleared already before authentication. */ |
---|
4041 | |
---|
4042 | /* Clear the data structure, just in case. */ |
---|
4043 | memset(&sensitive_data, 0, sizeof(sensitive_data)); |
---|
4044 | |
---|
4045 | #ifdef USELOGIN |
---|
4046 | if (command != NULL || !options.use_login) |
---|
4047 | #endif /* USELOGIN */ |
---|
4048 | { |
---|
4049 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
4050 | char *p, *s, **tmpenv; |
---|
4051 | |
---|
4052 | /* Initialize the new environment. |
---|
4053 | */ |
---|
4054 | envsize = 64; |
---|
4055 | env = xmalloc(envsize * sizeof(char *)); |
---|
4056 | env[0] = NULL; |
---|
4057 | |
---|
4058 | child_set_env(&env, &envsize, "PATH", DEFAULT_PATH); |
---|
4059 | |
---|
4060 | #ifdef MAIL_SPOOL_DIRECTORY |
---|
4061 | sprintf(buf, "%.200s/%.50s", MAIL_SPOOL_DIRECTORY, user_name); |
---|
4062 | child_set_env(&env, &envsize, "MAIL", buf); |
---|
4063 | #else /* MAIL_SPOOL_DIRECTORY */ |
---|
4064 | #ifdef MAIL_SPOOL_FILE |
---|
4065 | sprintf(buf, "%.200s/%.50s", user_dir, MAIL_SPOOL_FILE); |
---|
4066 | child_set_env(&env, &envsize, "MAIL", buf); |
---|
4067 | #endif /* MAIL_SPOOL_FILE */ |
---|
4068 | #endif /* MAIL_SPOOL_DIRECTORY */ |
---|
4069 | |
---|
4070 | /* Let it inherit timezone if we have one. */ |
---|
4071 | if (getenv("TZ")) |
---|
4072 | child_set_env(&env, &envsize, "TZ", getenv("TZ")); |
---|
4073 | |
---|
4074 | /* Save previous environment array |
---|
4075 | */ |
---|
4076 | tmpenv = environ; |
---|
4077 | environ = env; |
---|
4078 | |
---|
4079 | /* Set the user's login environment |
---|
4080 | */ |
---|
4081 | if (setusercontext(lc, pw, user_uid, LOGIN_SETALL) < 0) |
---|
4082 | { |
---|
4083 | perror("setusercontext"); |
---|
4084 | exit(1); |
---|
4085 | } |
---|
4086 | |
---|
4087 | p = getenv("PATH"); |
---|
4088 | s = xmalloc((p != NULL ? strlen(p) + 1 : 0) + sizeof(SSH_BINDIR)); |
---|
4089 | *s = '\0'; |
---|
4090 | if (p != NULL) |
---|
4091 | { |
---|
4092 | strcat(s, p); |
---|
4093 | strcat(s, ":"); |
---|
4094 | } |
---|
4095 | strcat(s, SSH_BINDIR); |
---|
4096 | |
---|
4097 | env = environ; |
---|
4098 | environ = tmpenv; /* Restore parent environment */ |
---|
4099 | for (envsize = 0; env[envsize] != NULL; ++envsize) |
---|
4100 | ; |
---|
4101 | /* Reallocate this to what is expected */ |
---|
4102 | envsize = (envsize < 100) ? 100 : envsize + 16; |
---|
4103 | env = xrealloc(env, envsize * sizeof(char *)); |
---|
4104 | |
---|
4105 | child_set_env(&env, &envsize, "PATH", s); |
---|
4106 | xfree(s); |
---|
4107 | |
---|
4108 | #else /* !HAVE_LOGIN_CAP_H */ |
---|
4109 | #if (_BSDI_VERSION > 199510) |
---|
4110 | if (setusercontext(lc, pw, user_uid, LOGIN_SETALL) < 0) |
---|
4111 | { |
---|
4112 | perror("setusercontext"); |
---|
4113 | exit(1); |
---|
4114 | } |
---|
4115 | if (auth_approve(lc, pw->pw_name, "ssh") <= 0) |
---|
4116 | { |
---|
4117 | perror("approval"); |
---|
4118 | exit(1); |
---|
4119 | } |
---|
4120 | #else /* (_BSDI_VERSION > 199510) */ |
---|
4121 | /* Set uid, gid, and groups. */ |
---|
4122 | if (getuid() == UID_ROOT || geteuid() == UID_ROOT) |
---|
4123 | { |
---|
4124 | if (setgid(user_gid) < 0) |
---|
4125 | { |
---|
4126 | perror("setgid"); |
---|
4127 | exit(1); |
---|
4128 | } |
---|
4129 | #ifdef HAVE_INITGROUPS |
---|
4130 | /* Initialize the group list. */ |
---|
4131 | if (initgroups(user_name, user_gid) < 0) |
---|
4132 | { |
---|
4133 | perror("initgroups"); |
---|
4134 | exit(1); |
---|
4135 | } |
---|
4136 | #endif /* HAVE_INITGROUPS */ |
---|
4137 | |
---|
4138 | /* Close any extra open file descriptors so that we don\'t have them |
---|
4139 | hanging around in clients. Note that we want to do this after |
---|
4140 | initgroups, because at least on Solaris 2.3 it leaves file |
---|
4141 | descriptors open. */ |
---|
4142 | endgrent(); |
---|
4143 | for (i = 3; i < 64; i++) |
---|
4144 | { |
---|
4145 | if (i == auth_get_fd()) |
---|
4146 | continue; |
---|
4147 | close(i); |
---|
4148 | } |
---|
4149 | |
---|
4150 | #ifdef KERBEROS |
---|
4151 | /* Chown ticket files to user */ |
---|
4152 | if (ticket && strcmp(ticket, "none")) |
---|
4153 | { |
---|
4154 | chown(ticket + 5, user_uid, user_gid); |
---|
4155 | chown(tkt_string(), user_uid, user_gid); |
---|
4156 | } |
---|
4157 | #endif |
---|
4158 | |
---|
4159 | /* At this point, this process should no longer be holding any |
---|
4160 | confidential information, as changing uid below will permit the |
---|
4161 | user to attach with a debugger on some machines. */ |
---|
4162 | |
---|
4163 | #ifdef CRAY /* set up accounting account number, job, limits, permissions */ |
---|
4164 | if (cray_setup(user_uid, user_name) < 0) |
---|
4165 | fatal("Failure performing Cray job setup for user %d.", |
---|
4166 | (int)user_uid); |
---|
4167 | #endif |
---|
4168 | |
---|
4169 | #ifdef HAVE_SETLUID |
---|
4170 | /* Set login uid, if we have setluid(). */ |
---|
4171 | if (setluid(user_uid) < 0) |
---|
4172 | fatal("setluid %d: %s", (int)user_uid, strerror(errno)); |
---|
4173 | #endif /* HAVE_SETLUID */ |
---|
4174 | |
---|
4175 | /* Permanently switch to the desired uid. */ |
---|
4176 | if (setuid(user_uid) < 0) |
---|
4177 | fatal("setuid %d: %s", (int)user_uid, strerror(errno)); |
---|
4178 | } |
---|
4179 | |
---|
4180 | if (getuid() != user_uid || geteuid() != user_uid) |
---|
4181 | fatal("Failed to set uids to %d.", (int)user_uid); |
---|
4182 | #endif /* (_BSDI_VERSION > 199510) */ |
---|
4183 | #endif /* HAVE_LOGIN_CAP_H */ |
---|
4184 | } |
---|
4185 | |
---|
4186 | /* Reset signals to their default settings before starting the user |
---|
4187 | process. */ |
---|
4188 | signals_reset(); |
---|
4189 | |
---|
4190 | #if defined(HAVE_OSF1_C2_SECURITY) |
---|
4191 | { |
---|
4192 | /* jcastro@ist.utl.pt Sep 1997 */ |
---|
4193 | extern long osflim[8]; |
---|
4194 | struct rlimit rl; |
---|
4195 | int i; |
---|
4196 | |
---|
4197 | for (i = 0; i < 8; i++) { |
---|
4198 | if (osflim[i] != -1) { |
---|
4199 | rl.rlim_cur= osflim[i]; |
---|
4200 | rl.rlim_max= osflim[i]; |
---|
4201 | setrlimit(i, &rl); |
---|
4202 | } |
---|
4203 | } |
---|
4204 | } |
---|
4205 | #endif |
---|
4206 | |
---|
4207 | /* Get the shell from the password data. An empty shell field is legal, |
---|
4208 | and means /bin/sh. */ |
---|
4209 | shell = (user_shell[0] == '\0') ? DEFAULT_SHELL : user_shell; |
---|
4210 | |
---|
4211 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
4212 | real_shell = login_getcapstr(lc, "shell", (char*)shell, (char*)shell); |
---|
4213 | login_close(lc); |
---|
4214 | #else /* !HAVE_LOGIN_CAP_H */ |
---|
4215 | /* Initialize the environment. In the first part we allocate space for |
---|
4216 | all environment variables. */ |
---|
4217 | envsize = 100; |
---|
4218 | env = xmalloc(envsize * sizeof(char *)); |
---|
4219 | env[0] = NULL; |
---|
4220 | #endif /* HAVE_LOGIN_CAP_H */ |
---|
4221 | |
---|
4222 | #ifdef USELOGIN |
---|
4223 | if (command != NULL || !options.use_login) |
---|
4224 | #endif /* USELOGIN */ |
---|
4225 | { |
---|
4226 | /* Set basic environment. */ |
---|
4227 | child_set_env(&env, &envsize, "HOME", user_dir); |
---|
4228 | child_set_env(&env, &envsize, "USER", user_name); |
---|
4229 | child_set_env(&env, &envsize, "LOGNAME", user_name); |
---|
4230 | |
---|
4231 | #ifndef HAVE_LOGIN_CAP_H |
---|
4232 | child_set_env(&env, &envsize, "PATH", DEFAULT_PATH ":" SSH_BINDIR); |
---|
4233 | |
---|
4234 | #ifdef MAIL_SPOOL_DIRECTORY |
---|
4235 | sprintf(buf, "%.200s/%.50s", MAIL_SPOOL_DIRECTORY, user_name); |
---|
4236 | child_set_env(&env, &envsize, "MAIL", buf); |
---|
4237 | #else /* MAIL_SPOOL_DIRECTORY */ |
---|
4238 | #ifdef MAIL_SPOOL_FILE |
---|
4239 | sprintf(buf, "%.200s/%.50s", user_dir, MAIL_SPOOL_FILE); |
---|
4240 | child_set_env(&env, &envsize, "MAIL", buf); |
---|
4241 | #endif /* MAIL_SPOOL_FILE */ |
---|
4242 | #endif /* MAIL_SPOOL_DIRECTORY */ |
---|
4243 | #endif /* !HAVE_LOGIN_CAP_H */ |
---|
4244 | |
---|
4245 | #ifdef HAVE_ETC_DEFAULT_LOGIN |
---|
4246 | /* Read /etc/default/login; this exists at least on Solaris 2.x. Note |
---|
4247 | that we are already running on the user's uid. */ |
---|
4248 | read_etc_default_login(&env, &envsize, user_shell, user_uid); |
---|
4249 | #else /* HAVE_ETC_DEFAULT_LOGIN */ |
---|
4250 | /* Normal systems set SHELL by default. */ |
---|
4251 | child_set_env(&env, &envsize, "SHELL", shell); |
---|
4252 | #endif /* HAVE_ETC_DEFAULT_LOGIN */ |
---|
4253 | } |
---|
4254 | |
---|
4255 | if (original_command != NULL) |
---|
4256 | child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", |
---|
4257 | original_command); |
---|
4258 | |
---|
4259 | #ifndef HAVE_LOGIN_CAP_H |
---|
4260 | /* Let it inherit timezone if we have one. */ |
---|
4261 | if (getenv("TZ")) |
---|
4262 | child_set_env(&env, &envsize, "TZ", getenv("TZ")); |
---|
4263 | #endif /* !HAVE_LOGIN_CAP_H */ |
---|
4264 | |
---|
4265 | /* Set custom environment options from RSA authentication. */ |
---|
4266 | while (custom_environment) |
---|
4267 | { |
---|
4268 | struct envstring *ce = custom_environment; |
---|
4269 | char *s = ce->s; |
---|
4270 | int i; |
---|
4271 | for (i = 0; s[i] != '=' && s[i]; i++) |
---|
4272 | ; |
---|
4273 | if (s[i] == '=') |
---|
4274 | { |
---|
4275 | s[i] = 0; |
---|
4276 | child_set_env(&env, &envsize, s, s + i + 1); |
---|
4277 | } |
---|
4278 | custom_environment = ce->next; |
---|
4279 | xfree(ce->s); |
---|
4280 | xfree(ce); |
---|
4281 | } |
---|
4282 | |
---|
4283 | /* Set SSH_CLIENT. */ |
---|
4284 | sprintf(buf, "%.50s %d %d", remote_ip, remote_port, options.port); |
---|
4285 | child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
---|
4286 | |
---|
4287 | /* Set SSH_TTY if we have a pty. */ |
---|
4288 | if (ttyname) |
---|
4289 | child_set_env(&env, &envsize, "SSH_TTY", ttyname); |
---|
4290 | |
---|
4291 | /* Set TERM if we have a pty. */ |
---|
4292 | if (term) |
---|
4293 | child_set_env(&env, &envsize, "TERM", term); |
---|
4294 | |
---|
4295 | /* Set DISPLAY if we have one. */ |
---|
4296 | if (display) |
---|
4297 | child_set_env(&env, &envsize, "DISPLAY", display); |
---|
4298 | |
---|
4299 | /* Set REMOTEUSER if available */ |
---|
4300 | if (remote_user_name) |
---|
4301 | child_set_env(&env, &envsize, "REMOTEUSER", remote_user_name); |
---|
4302 | |
---|
4303 | #if defined(_AIX) && defined(HAVE_AUTHENTICATE) |
---|
4304 | { |
---|
4305 | char *authstate, *krb5cc; |
---|
4306 | |
---|
4307 | /* Set AUTHSTATE if we have AUTHSTATE. */ |
---|
4308 | if ((authstate = getenv("AUTHSTATE")) != NULL) |
---|
4309 | child_set_env(&env, &envsize, "AUTHSTATE", authstate); |
---|
4310 | |
---|
4311 | /* Set KRB5CCNAME if we have KRB5CCNAME. */ |
---|
4312 | if ((krb5cc = getenv("KRB5CCNAME")) != NULL) |
---|
4313 | child_set_env(&env, &envsize, "KRB5CCNAME", krb5cc); |
---|
4314 | } |
---|
4315 | #endif |
---|
4316 | |
---|
4317 | #ifdef KERBEROS |
---|
4318 | /* Set KRBTKFILE to point to our ticket */ |
---|
4319 | #ifdef KRB5 |
---|
4320 | if (ticket && strcmp(ticket, "none")) |
---|
4321 | { |
---|
4322 | child_set_env(&env, &envsize, "KRB5CCNAME", ticket); |
---|
4323 | child_set_env(&env, &envsize, "KRBTKFILE", tkt_string()); |
---|
4324 | } |
---|
4325 | #endif /* KRB5 */ |
---|
4326 | #endif /* KERBEROS */ |
---|
4327 | |
---|
4328 | /* Set variable for forwarded authentication connection, if we have one. */ |
---|
4329 | if (auth_get_socket_name() != NULL) |
---|
4330 | child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, |
---|
4331 | auth_get_socket_name()); |
---|
4332 | |
---|
4333 | /* Set XAUTHORITY to something safe. (we don't want to put the xauth |
---|
4334 | cookie into AFS.) */ |
---|
4335 | if (auth_proto != NULL && auth_data != NULL) |
---|
4336 | { |
---|
4337 | sprintf(buf, "/tmp/xauth-%s-%d", user_name, (int)getpid()); |
---|
4338 | if (mkdir(buf, S_IRWXU) == -1) |
---|
4339 | { |
---|
4340 | fprintf(stderr, "Could not create xauth directory %s: %s\n" |
---|
4341 | "Disabling X forwarding.\n", buf, strerror(errno)); |
---|
4342 | auth_proto = auth_data = NULL; |
---|
4343 | } |
---|
4344 | else |
---|
4345 | { |
---|
4346 | strcat(buf, "/Xauthority"); |
---|
4347 | child_set_env(&env, &envsize, "XAUTHORITY", buf); |
---|
4348 | } |
---|
4349 | } |
---|
4350 | |
---|
4351 | #ifdef USELOGIN |
---|
4352 | if (command != NULL || !options.use_login) |
---|
4353 | #endif /* USELOGIN */ |
---|
4354 | { |
---|
4355 | /* Read environment variable settings from /etc/environment. (This |
---|
4356 | exists at least on AIX, but could be useful also elsewhere.) */ |
---|
4357 | read_environment_file(&env, &envsize, "/etc/environment"); |
---|
4358 | |
---|
4359 | /* Read $HOME/.ssh/environment. */ |
---|
4360 | sprintf(buf, "%.200s/.ssh/environment", user_dir); |
---|
4361 | read_environment_file(&env, &envsize, buf); |
---|
4362 | |
---|
4363 | /* Change current directory to the user\'s home directory. */ |
---|
4364 | if (chdir(user_dir) < 0) |
---|
4365 | fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
---|
4366 | user_dir, strerror(errno)); |
---|
4367 | } |
---|
4368 | |
---|
4369 | /* If debugging, dump the environment to stderr. */ |
---|
4370 | if (debug_flag) |
---|
4371 | { |
---|
4372 | fprintf(stderr, "Environment:\n"); |
---|
4373 | for (i = 0; env[i]; i++) |
---|
4374 | fprintf(stderr, " %.200s\n", env[i]); |
---|
4375 | fprintf(stderr, "\n"); |
---|
4376 | } |
---|
4377 | |
---|
4378 | |
---|
4379 | /* Must take new environment into use so that .ssh/rc, /etc/sshrc and |
---|
4380 | xauth are run in the proper environment. */ |
---|
4381 | environ = env; |
---|
4382 | |
---|
4383 | #ifdef USELOGIN |
---|
4384 | if (command != NULL || !options.use_login) |
---|
4385 | #endif /* USELOGIN */ |
---|
4386 | { |
---|
4387 | /* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first |
---|
4388 | in this order). Note that we are already running on the user's |
---|
4389 | uid. */ |
---|
4390 | if (stat(SSH_USER_RC, &st) >= 0) |
---|
4391 | { |
---|
4392 | sprintf(buf, "%.100s %.100s", shell, SSH_USER_RC); |
---|
4393 | |
---|
4394 | if (debug_flag) |
---|
4395 | fprintf(stderr, "Running %s\n", buf); |
---|
4396 | |
---|
4397 | f = popen(buf, "w"); |
---|
4398 | if (f) |
---|
4399 | { |
---|
4400 | if (auth_proto != NULL && auth_data != NULL) |
---|
4401 | fprintf(f, "%s %s\n", auth_proto, auth_data); |
---|
4402 | pclose(f); |
---|
4403 | } |
---|
4404 | else |
---|
4405 | fprintf(stderr, "Could not run %s\n", SSH_USER_RC); |
---|
4406 | } |
---|
4407 | else |
---|
4408 | if (stat(SSH_SYSTEM_RC, &st) >= 0) |
---|
4409 | { |
---|
4410 | sprintf(buf, "%.100s %.100s", "/bin/sh", SSH_SYSTEM_RC); |
---|
4411 | |
---|
4412 | if (debug_flag) |
---|
4413 | fprintf(stderr, "Running %s\n", buf); |
---|
4414 | |
---|
4415 | f = popen(buf, "w"); |
---|
4416 | if (f) |
---|
4417 | { |
---|
4418 | if (auth_proto != NULL && auth_data != NULL) |
---|
4419 | fprintf(f, "%s %s\n", auth_proto, auth_data); |
---|
4420 | pclose(f); |
---|
4421 | } |
---|
4422 | else |
---|
4423 | fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC); |
---|
4424 | } |
---|
4425 | #ifdef XAUTH_PATH |
---|
4426 | else |
---|
4427 | { |
---|
4428 | /* Add authority data to .Xauthority if appropriate. */ |
---|
4429 | if (auth_proto != NULL && auth_data != NULL) |
---|
4430 | { |
---|
4431 | int i; |
---|
4432 | char name[255], *p; |
---|
4433 | char line[256]; |
---|
4434 | struct hostent *hp; |
---|
4435 | |
---|
4436 | strncpy(name, display, sizeof(name)); |
---|
4437 | name[sizeof(name) - 1] = '\0'; |
---|
4438 | p = strchr(name, ':'); |
---|
4439 | if (p) |
---|
4440 | *p = '\0'; |
---|
4441 | |
---|
4442 | if (debug_flag) |
---|
4443 | fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n", |
---|
4444 | options.xauth_path, display, auth_proto, auth_data); |
---|
4445 | |
---|
4446 | signal(SIGPIPE, SIG_IGN); |
---|
4447 | |
---|
4448 | sprintf(line, "%.200s -q -", options.xauth_path); |
---|
4449 | f = popen(line, "w"); |
---|
4450 | if (f) |
---|
4451 | { |
---|
4452 | fprintf(f, "add %s %s %s\n", display, auth_proto, |
---|
4453 | auth_data); |
---|
4454 | cp = strchr(display, ':'); |
---|
4455 | if (cp) |
---|
4456 | { |
---|
4457 | #ifndef CRAY |
---|
4458 | /* Cray xauth cannot take host/unix:0 as displayname */ |
---|
4459 | fprintf(f, "add %.*s/unix%s %s %s\n", |
---|
4460 | cp - display, display, cp, auth_proto, |
---|
4461 | auth_data); |
---|
4462 | #endif |
---|
4463 | hp = gethostbyname(name); |
---|
4464 | if (hp) |
---|
4465 | { |
---|
4466 | for(i = 0; hp->h_addr_list[i]; i++) |
---|
4467 | { |
---|
4468 | if (debug_flag) |
---|
4469 | { |
---|
4470 | fprintf(stderr, "Running %s add %s%s %s %s\n", |
---|
4471 | options.xauth_path, |
---|
4472 | inet_ntoa(*((struct in_addr *) |
---|
4473 | hp->h_addr_list[i])), |
---|
4474 | cp, auth_proto, auth_data); |
---|
4475 | } |
---|
4476 | fprintf(f, "add %s%s %s %s\n", |
---|
4477 | inet_ntoa(*((struct in_addr *) |
---|
4478 | hp->h_addr_list[i])), |
---|
4479 | cp, auth_proto, auth_data); |
---|
4480 | } |
---|
4481 | } |
---|
4482 | } |
---|
4483 | pclose(f); |
---|
4484 | } |
---|
4485 | else |
---|
4486 | fprintf(stderr, "Could not run %s -q -\n", |
---|
4487 | options.xauth_path); |
---|
4488 | |
---|
4489 | signal(SIGPIPE, SIG_DFL); |
---|
4490 | } |
---|
4491 | } |
---|
4492 | #endif /* XAUTH_PATH */ |
---|
4493 | } |
---|
4494 | |
---|
4495 | #ifdef USELOGIN |
---|
4496 | if (command != NULL || !options.use_login) |
---|
4497 | #endif /* USELOGIN */ |
---|
4498 | { |
---|
4499 | /* Get the last component of the shell name. */ |
---|
4500 | cp = strrchr(shell, '/'); |
---|
4501 | if (cp) |
---|
4502 | cp++; |
---|
4503 | else |
---|
4504 | cp = shell; |
---|
4505 | } |
---|
4506 | |
---|
4507 | /* If we have no command, execute the shell. In this case, the shell name |
---|
4508 | to be passed in argv[0] is preceded by '-' to indicate that this is |
---|
4509 | a login shell. */ |
---|
4510 | if (!command) |
---|
4511 | { |
---|
4512 | #ifdef USELOGIN |
---|
4513 | if (!options.use_login) |
---|
4514 | #endif /* USELOGIN */ |
---|
4515 | { |
---|
4516 | char buf[256]; |
---|
4517 | |
---|
4518 | if (options.check_mail) |
---|
4519 | { |
---|
4520 | char *mailbox; |
---|
4521 | |
---|
4522 | mailbox = getenv("MAIL"); |
---|
4523 | if(mailbox != NULL) |
---|
4524 | { |
---|
4525 | struct stat mailbuf; |
---|
4526 | |
---|
4527 | if (stat(mailbox, &mailbuf) == -1 || mailbuf.st_size == 0) |
---|
4528 | printf("No mail.\n"); |
---|
4529 | else if (mailbuf.st_atime > mailbuf.st_mtime) |
---|
4530 | printf("You have mail.\n"); |
---|
4531 | else |
---|
4532 | printf("You have new mail.\n"); |
---|
4533 | } |
---|
4534 | } |
---|
4535 | if (days_before_account_expires >= 0 && |
---|
4536 | days_before_account_expires < |
---|
4537 | options.account_expire_warning_days) |
---|
4538 | { |
---|
4539 | printf("\n\tWARNING: Your account expires in %d days\n\n", |
---|
4540 | days_before_account_expires); |
---|
4541 | } |
---|
4542 | if (days_before_password_expires >= 0 && |
---|
4543 | days_before_password_expires < |
---|
4544 | options.password_expire_warning_days) |
---|
4545 | { |
---|
4546 | printf("\n\tWARNING: Your password expires in %d days\n\n", |
---|
4547 | days_before_password_expires); |
---|
4548 | } |
---|
4549 | |
---|
4550 | /* Start the shell. Set initial character to '-'. */ |
---|
4551 | buf[0] = '-'; |
---|
4552 | strncpy(buf + 1, cp, sizeof(buf) - 1); |
---|
4553 | buf[sizeof(buf) - 1] = 0; |
---|
4554 | /* Execute the shell. */ |
---|
4555 | argv[0] = buf; |
---|
4556 | argv[1] = NULL; |
---|
4557 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
4558 | execve(real_shell, argv, env); |
---|
4559 | #else |
---|
4560 | execve(shell, argv, env); |
---|
4561 | #endif /* HAVE_LOGIN_CAP_H */ |
---|
4562 | /* Executing the shell failed. */ |
---|
4563 | perror(shell); |
---|
4564 | exit(1); |
---|
4565 | } |
---|
4566 | #ifdef USELOGIN |
---|
4567 | else |
---|
4568 | { |
---|
4569 | execl(PATH_LOGIN, "login", "-h", remote_ip, "-p", "-f", |
---|
4570 | "--", user_name, NULL); |
---|
4571 | /* NOTREACHED */ |
---|
4572 | } |
---|
4573 | #endif /* USELOGIN */ |
---|
4574 | } |
---|
4575 | |
---|
4576 | /* Execute the command using the user's shell. This uses the -c option |
---|
4577 | to execute the command. */ |
---|
4578 | argv[0] = (char *)cp; |
---|
4579 | argv[1] = "-c"; |
---|
4580 | argv[2] = (char *)command; |
---|
4581 | argv[3] = NULL; |
---|
4582 | #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H) |
---|
4583 | execve(real_shell, argv, env); |
---|
4584 | #else |
---|
4585 | execve(shell, argv, env); |
---|
4586 | #endif /* HAVE_LOGIN_CAP_H */ |
---|
4587 | perror(shell); |
---|
4588 | exit(1); |
---|
4589 | } |
---|
4590 | |
---|
4591 | #ifdef CRAY |
---|
4592 | /* |
---|
4593 | On a Cray, set the account number for the current process to the user's |
---|
4594 | default account. If this is not done, the process will have an account |
---|
4595 | of zero and accounting (Cray System Accounting and/or SDSC Resource |
---|
4596 | Management (realtime)) will not operate correctly. |
---|
4597 | |
---|
4598 | This routine also calls setjob to set up an Cray Job (also known |
---|
4599 | as a Session). This is needed for CRI's Cray System Accounting |
---|
4600 | and SDSC's Resource Management accounting/management system. |
---|
4601 | |
---|
4602 | It also calls setlimit, to set up limits and permissions. |
---|
4603 | |
---|
4604 | Wayne Schroeder |
---|
4605 | San Diego Supercomputer Center |
---|
4606 | schroeder@sdsc.edu |
---|
4607 | |
---|
4608 | */ |
---|
4609 | int cray_setup(uid, username) |
---|
4610 | uid_t uid; |
---|
4611 | char *username; |
---|
4612 | { |
---|
4613 | register struct udb *p; |
---|
4614 | extern struct udb *getudb(); |
---|
4615 | int i, j; |
---|
4616 | int accts[MAXVIDS]; |
---|
4617 | int naccts; |
---|
4618 | int err, jid; |
---|
4619 | char *sr; |
---|
4620 | int pid; |
---|
4621 | |
---|
4622 | /* Find all of the accounts for a particular user */ |
---|
4623 | err = setudb(); /* open and rewind the Cray User DataBase */ |
---|
4624 | if(err != 0) |
---|
4625 | { |
---|
4626 | debug("UDB open failure"); |
---|
4627 | return(-1); |
---|
4628 | } |
---|
4629 | naccts = 0; |
---|
4630 | while ((p = getudb()) != UDB_NULL) |
---|
4631 | { |
---|
4632 | if (p->ue_uid == -1) break; |
---|
4633 | if(uid == p->ue_uid) |
---|
4634 | { |
---|
4635 | for(j = 0; p->ue_acids[j] != -1 && j < MAXVIDS; j++) |
---|
4636 | { |
---|
4637 | accts[naccts] = p->ue_acids[j]; |
---|
4638 | naccts++; |
---|
4639 | } |
---|
4640 | } |
---|
4641 | } |
---|
4642 | endudb(); /* close the udb */ |
---|
4643 | if (naccts == 0 || accts[0] == 0) |
---|
4644 | { |
---|
4645 | debug("No Cray accounts found"); |
---|
4646 | return(-1); |
---|
4647 | } |
---|
4648 | |
---|
4649 | /* Perhaps someday we'll prompt users who have multiple accounts |
---|
4650 | to let them pick one (like CRI's login does), but for now just set |
---|
4651 | the account to the first entry. */ |
---|
4652 | if (acctid(0, accts[0]) < 0) |
---|
4653 | { |
---|
4654 | debug("System call acctid failed, accts[0]=%d",accts[0]); |
---|
4655 | return(-1); |
---|
4656 | } |
---|
4657 | |
---|
4658 | /* Now call setjob to create a new job(/session). This assigns a new Session |
---|
4659 | ID and session table entry to the calling process. This process will be |
---|
4660 | the first process in the job/session. */ |
---|
4661 | jid = setjob(uid, 0); |
---|
4662 | if (jid < 0) |
---|
4663 | { |
---|
4664 | debug("System call setjob failure"); |
---|
4665 | return(-1); |
---|
4666 | } |
---|
4667 | |
---|
4668 | /* Now set limits, including CPU time for the (interactive) job and process, |
---|
4669 | and set up permissions (for chown etc), etc. This is via an internal CRI |
---|
4670 | routine, setlimits, used by CRI's login. */ |
---|
4671 | |
---|
4672 | pid = getpid(); |
---|
4673 | sr = setlimits(username, C_PROC, pid, UDBRC_INTER); |
---|
4674 | if (sr != NULL) |
---|
4675 | { |
---|
4676 | debug(sr); |
---|
4677 | return(-1); |
---|
4678 | } |
---|
4679 | sr = setlimits(username, C_JOB, jid, UDBRC_INTER); |
---|
4680 | if (sr != NULL) |
---|
4681 | { |
---|
4682 | debug(sr); |
---|
4683 | return(-1); |
---|
4684 | } |
---|
4685 | |
---|
4686 | return(0); |
---|
4687 | } |
---|
4688 | #endif /* CRAY */ |
---|
4689 | |
---|
4690 | void try_afscall(int (*func)(void)) |
---|
4691 | { |
---|
4692 | #ifdef SIGSYS |
---|
4693 | struct sigaction sa, osa; |
---|
4694 | |
---|
4695 | sigemptyset(&sa.sa_mask); |
---|
4696 | sa.sa_flags = 0; |
---|
4697 | sa.sa_handler = SIG_IGN; |
---|
4698 | sigaction(SIGSYS, &sa, &osa); |
---|
4699 | #endif |
---|
4700 | func(); |
---|
4701 | #ifdef SIGSYS |
---|
4702 | sigaction(SIGSYS, &osa, NULL); |
---|
4703 | #endif |
---|
4704 | } |
---|
4705 | |
---|
4706 | void al_cleanup(void) |
---|
4707 | { |
---|
4708 | al_acct_revert(al_user, getpid()); |
---|
4709 | } |
---|
4710 | |
---|
4711 | void krb_cleanup(void) |
---|
4712 | { |
---|
4713 | if (ticket && strcmp(ticket, "none")) |
---|
4714 | { |
---|
4715 | krb5_ccache ccache; |
---|
4716 | if (!krb5_cc_resolve(ssh_context, ticket, &ccache)) |
---|
4717 | krb5_cc_destroy(ssh_context, ccache); |
---|
4718 | dest_tkt(); |
---|
4719 | try_afscall(ktc_ForgetAllTokens); |
---|
4720 | } |
---|
4721 | } |
---|