openssh/servconf.c

2556 lines
75 KiB
C
Raw Normal View History

/* $OpenBSD: servconf.c,v 1.317 2017/10/25 00:19:47 djm Exp $ */
1999-10-27 11:42:43 +08:00
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 10:29:08 +08:00
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
1999-10-27 11:42:43 +08:00
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifdef HAVE_NET_ROUTE_H
#include <net/route.h>
#endif
#include <ctype.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 10:39:39 +08:00
#include <signal.h>
#include <unistd.h>
#include <limits.h>
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 10:39:39 +08:00
#include <stdarg.h>
#include <errno.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#include "openbsd-compat/sys-queue.h"
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 10:39:39 +08:00
#include "xmalloc.h"
1999-10-27 11:42:43 +08:00
#include "ssh.h"
Hopefully things did not get mixed around too much. It compiles under Linux and works. So that is at least a good sign. =) 20010122 - (bal) OpenBSD Resync - markus@cvs.openbsd.org 2001/01/19 12:45:26 GMT 2001 by markus [servconf.c ssh.h sshd.c] only auth-chall.c needs #ifdef SKEY - markus@cvs.openbsd.org 2001/01/19 15:55:10 GMT 2001 by markus [auth-krb4.c auth-options.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c auth2.c channels.c clientloop.c dh.c dispatch.c nchan.c packet.c pathname.h readconf.c scp.c servconf.c serverloop.c session.c ssh-add.c ssh-keygen.c ssh-keyscan.c ssh.c ssh.h ssh1.h sshconnect1.c sshd.c ttymodes.c] move ssh1 definitions to ssh1.h, pathnames to pathnames.h - markus@cvs.openbsd.org 2001/01/19 16:48:14 [sshd.8] fix typo; from stevesk@ - markus@cvs.openbsd.org 2001/01/19 16:50:58 [ssh-dss.c] clear and free digest, make consistent with other code (use dlen); from stevesk@ - markus@cvs.openbsd.org 2001/01/20 15:55:20 GMT 2001 by markus [auth-options.c auth-options.h auth-rsa.c auth2.c] pass the filename to auth_parse_options() - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001 [readconf.c] fix SIGSEGV from -o ""; problem noted by jehsom@togetherweb.com - stevesk@cvs.openbsd.org 2001/01/20 18:20:29 [sshconnect2.c] dh_new_group() does not return NULL. ok markus@ - markus@cvs.openbsd.org 2001/01/20 21:33:42 [ssh-add.c] do not loop forever if askpass does not exist; from andrew@pimlott.ne.mediaone.net - djm@cvs.openbsd.org 2001/01/20 23:00:56 [servconf.c] Check for NULL return from strdelim; ok markus - djm@cvs.openbsd.org 2001/01/20 23:02:07 [readconf.c] KNF; ok markus - jakob@cvs.openbsd.org 2001/01/21 9:00:33 [ssh-keygen.1] remove -R flag; ok markus@ - markus@cvs.openbsd.org 2001/01/21 19:05:40 [atomicio.c automicio.h auth-chall.c auth-krb4.c auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth.c auth.h auth1.c auth2-chall.c auth2.c authfd.c authfile.c bufaux.c bufaux.h buffer.c canahost.c canahost.h channels.c cipher.c cli.c clientloop.c clientloop.h compat.c compress.c deattack.c dh.c dispatch.c groupaccess.c hmac.c hostfile.c kex.c key.c key.h log-client.c log-server.c log.c log.h login.c login.h match.c misc.c misc.h nchan.c packet.c pty.c radix.h readconf.c readpass.c readpass.h rsa.c scp.c servconf.c serverloop.c serverloop.h session.c sftp-server.c ssh-add.c ssh-agent.c ssh-dss.c ssh-keygen.c ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c sshd.c tildexpand.c tildexpand.h ttysmodes.c uidswap.c xmalloc.c] split ssh.h and try to cleanup the #include mess. remove unnecessary #includes. rename util.[ch] -> misc.[ch] - (bal) renamed 'PIDDIR' to '_PATH_SSH_PIDDIR' to match OpenBSD tree - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve conflict when compiling for non-kerb install - (bal) removed the #ifdef SKEY in auth1.c to match Markus' changes on 1/19.
2001-01-22 13:34:40 +08:00
#include "log.h"
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 10:39:39 +08:00
#include "buffer.h"
#include "misc.h"
1999-10-27 11:42:43 +08:00
#include "servconf.h"
#include "compat.h"
Hopefully things did not get mixed around too much. It compiles under Linux and works. So that is at least a good sign. =) 20010122 - (bal) OpenBSD Resync - markus@cvs.openbsd.org 2001/01/19 12:45:26 GMT 2001 by markus [servconf.c ssh.h sshd.c] only auth-chall.c needs #ifdef SKEY - markus@cvs.openbsd.org 2001/01/19 15:55:10 GMT 2001 by markus [auth-krb4.c auth-options.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c auth2.c channels.c clientloop.c dh.c dispatch.c nchan.c packet.c pathname.h readconf.c scp.c servconf.c serverloop.c session.c ssh-add.c ssh-keygen.c ssh-keyscan.c ssh.c ssh.h ssh1.h sshconnect1.c sshd.c ttymodes.c] move ssh1 definitions to ssh1.h, pathnames to pathnames.h - markus@cvs.openbsd.org 2001/01/19 16:48:14 [sshd.8] fix typo; from stevesk@ - markus@cvs.openbsd.org 2001/01/19 16:50:58 [ssh-dss.c] clear and free digest, make consistent with other code (use dlen); from stevesk@ - markus@cvs.openbsd.org 2001/01/20 15:55:20 GMT 2001 by markus [auth-options.c auth-options.h auth-rsa.c auth2.c] pass the filename to auth_parse_options() - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001 [readconf.c] fix SIGSEGV from -o ""; problem noted by jehsom@togetherweb.com - stevesk@cvs.openbsd.org 2001/01/20 18:20:29 [sshconnect2.c] dh_new_group() does not return NULL. ok markus@ - markus@cvs.openbsd.org 2001/01/20 21:33:42 [ssh-add.c] do not loop forever if askpass does not exist; from andrew@pimlott.ne.mediaone.net - djm@cvs.openbsd.org 2001/01/20 23:00:56 [servconf.c] Check for NULL return from strdelim; ok markus - djm@cvs.openbsd.org 2001/01/20 23:02:07 [readconf.c] KNF; ok markus - jakob@cvs.openbsd.org 2001/01/21 9:00:33 [ssh-keygen.1] remove -R flag; ok markus@ - markus@cvs.openbsd.org 2001/01/21 19:05:40 [atomicio.c automicio.h auth-chall.c auth-krb4.c auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth.c auth.h auth1.c auth2-chall.c auth2.c authfd.c authfile.c bufaux.c bufaux.h buffer.c canahost.c canahost.h channels.c cipher.c cli.c clientloop.c clientloop.h compat.c compress.c deattack.c dh.c dispatch.c groupaccess.c hmac.c hostfile.c kex.c key.c key.h log-client.c log-server.c log.c log.h login.c login.h match.c misc.c misc.h nchan.c packet.c pty.c radix.h readconf.c readpass.c readpass.h rsa.c scp.c servconf.c serverloop.c serverloop.h session.c sftp-server.c ssh-add.c ssh-agent.c ssh-dss.c ssh-keygen.c ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c sshd.c tildexpand.c tildexpand.h ttysmodes.c uidswap.c xmalloc.c] split ssh.h and try to cleanup the #include mess. remove unnecessary #includes. rename util.[ch] -> misc.[ch] - (bal) renamed 'PIDDIR' to '_PATH_SSH_PIDDIR' to match OpenBSD tree - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve conflict when compiling for non-kerb install - (bal) removed the #ifdef SKEY in auth1.c to match Markus' changes on 1/19.
2001-01-22 13:34:40 +08:00
#include "pathnames.h"
#include "cipher.h"
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 10:39:39 +08:00
#include "key.h"
#include "kex.h"
#include "mac.h"
#include "match.h"
#include "channels.h"
#include "groupaccess.h"
#include "canohost.h"
#include "packet.h"
#include "hostfile.h"
#include "auth.h"
#include "myproposal.h"
#include "digest.h"
Hopefully things did not get mixed around too much. It compiles under Linux and works. So that is at least a good sign. =) 20010122 - (bal) OpenBSD Resync - markus@cvs.openbsd.org 2001/01/19 12:45:26 GMT 2001 by markus [servconf.c ssh.h sshd.c] only auth-chall.c needs #ifdef SKEY - markus@cvs.openbsd.org 2001/01/19 15:55:10 GMT 2001 by markus [auth-krb4.c auth-options.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c auth2.c channels.c clientloop.c dh.c dispatch.c nchan.c packet.c pathname.h readconf.c scp.c servconf.c serverloop.c session.c ssh-add.c ssh-keygen.c ssh-keyscan.c ssh.c ssh.h ssh1.h sshconnect1.c sshd.c ttymodes.c] move ssh1 definitions to ssh1.h, pathnames to pathnames.h - markus@cvs.openbsd.org 2001/01/19 16:48:14 [sshd.8] fix typo; from stevesk@ - markus@cvs.openbsd.org 2001/01/19 16:50:58 [ssh-dss.c] clear and free digest, make consistent with other code (use dlen); from stevesk@ - markus@cvs.openbsd.org 2001/01/20 15:55:20 GMT 2001 by markus [auth-options.c auth-options.h auth-rsa.c auth2.c] pass the filename to auth_parse_options() - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001 [readconf.c] fix SIGSEGV from -o ""; problem noted by jehsom@togetherweb.com - stevesk@cvs.openbsd.org 2001/01/20 18:20:29 [sshconnect2.c] dh_new_group() does not return NULL. ok markus@ - markus@cvs.openbsd.org 2001/01/20 21:33:42 [ssh-add.c] do not loop forever if askpass does not exist; from andrew@pimlott.ne.mediaone.net - djm@cvs.openbsd.org 2001/01/20 23:00:56 [servconf.c] Check for NULL return from strdelim; ok markus - djm@cvs.openbsd.org 2001/01/20 23:02:07 [readconf.c] KNF; ok markus - jakob@cvs.openbsd.org 2001/01/21 9:00:33 [ssh-keygen.1] remove -R flag; ok markus@ - markus@cvs.openbsd.org 2001/01/21 19:05:40 [atomicio.c automicio.h auth-chall.c auth-krb4.c auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth.c auth.h auth1.c auth2-chall.c auth2.c authfd.c authfile.c bufaux.c bufaux.h buffer.c canahost.c canahost.h channels.c cipher.c cli.c clientloop.c clientloop.h compat.c compress.c deattack.c dh.c dispatch.c groupaccess.c hmac.c hostfile.c kex.c key.c key.h log-client.c log-server.c log.c log.h login.c login.h match.c misc.c misc.h nchan.c packet.c pty.c radix.h readconf.c readpass.c readpass.h rsa.c scp.c servconf.c serverloop.c serverloop.h session.c sftp-server.c ssh-add.c ssh-agent.c ssh-dss.c ssh-keygen.c ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c sshd.c tildexpand.c tildexpand.h ttysmodes.c uidswap.c xmalloc.c] split ssh.h and try to cleanup the #include mess. remove unnecessary #includes. rename util.[ch] -> misc.[ch] - (bal) renamed 'PIDDIR' to '_PATH_SSH_PIDDIR' to match OpenBSD tree - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve conflict when compiling for non-kerb install - (bal) removed the #ifdef SKEY in auth1.c to match Markus' changes on 1/19.
2001-01-22 13:34:40 +08:00
static void add_listen_addr(ServerOptions *, const char *,
const char *, int);
static void add_one_listen_addr(ServerOptions *, const char *,
const char *, int);
/* Use of privilege separation or not */
extern int use_privsep;
extern Buffer cfg;
Hopefully things did not get mixed around too much. It compiles under Linux and works. So that is at least a good sign. =) 20010122 - (bal) OpenBSD Resync - markus@cvs.openbsd.org 2001/01/19 12:45:26 GMT 2001 by markus [servconf.c ssh.h sshd.c] only auth-chall.c needs #ifdef SKEY - markus@cvs.openbsd.org 2001/01/19 15:55:10 GMT 2001 by markus [auth-krb4.c auth-options.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c auth2.c channels.c clientloop.c dh.c dispatch.c nchan.c packet.c pathname.h readconf.c scp.c servconf.c serverloop.c session.c ssh-add.c ssh-keygen.c ssh-keyscan.c ssh.c ssh.h ssh1.h sshconnect1.c sshd.c ttymodes.c] move ssh1 definitions to ssh1.h, pathnames to pathnames.h - markus@cvs.openbsd.org 2001/01/19 16:48:14 [sshd.8] fix typo; from stevesk@ - markus@cvs.openbsd.org 2001/01/19 16:50:58 [ssh-dss.c] clear and free digest, make consistent with other code (use dlen); from stevesk@ - markus@cvs.openbsd.org 2001/01/20 15:55:20 GMT 2001 by markus [auth-options.c auth-options.h auth-rsa.c auth2.c] pass the filename to auth_parse_options() - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001 [readconf.c] fix SIGSEGV from -o ""; problem noted by jehsom@togetherweb.com - stevesk@cvs.openbsd.org 2001/01/20 18:20:29 [sshconnect2.c] dh_new_group() does not return NULL. ok markus@ - markus@cvs.openbsd.org 2001/01/20 21:33:42 [ssh-add.c] do not loop forever if askpass does not exist; from andrew@pimlott.ne.mediaone.net - djm@cvs.openbsd.org 2001/01/20 23:00:56 [servconf.c] Check for NULL return from strdelim; ok markus - djm@cvs.openbsd.org 2001/01/20 23:02:07 [readconf.c] KNF; ok markus - jakob@cvs.openbsd.org 2001/01/21 9:00:33 [ssh-keygen.1] remove -R flag; ok markus@ - markus@cvs.openbsd.org 2001/01/21 19:05:40 [atomicio.c automicio.h auth-chall.c auth-krb4.c auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth.c auth.h auth1.c auth2-chall.c auth2.c authfd.c authfile.c bufaux.c bufaux.h buffer.c canahost.c canahost.h channels.c cipher.c cli.c clientloop.c clientloop.h compat.c compress.c deattack.c dh.c dispatch.c groupaccess.c hmac.c hostfile.c kex.c key.c key.h log-client.c log-server.c log.c log.h login.c login.h match.c misc.c misc.h nchan.c packet.c pty.c radix.h readconf.c readpass.c readpass.h rsa.c scp.c servconf.c serverloop.c serverloop.h session.c sftp-server.c ssh-add.c ssh-agent.c ssh-dss.c ssh-keygen.c ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c sshd.c tildexpand.c tildexpand.h ttysmodes.c uidswap.c xmalloc.c] split ssh.h and try to cleanup the #include mess. remove unnecessary #includes. rename util.[ch] -> misc.[ch] - (bal) renamed 'PIDDIR' to '_PATH_SSH_PIDDIR' to match OpenBSD tree - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve conflict when compiling for non-kerb install - (bal) removed the #ifdef SKEY in auth1.c to match Markus' changes on 1/19.
2001-01-22 13:34:40 +08:00
1999-10-27 11:42:43 +08:00
/* Initializes the server options to their default values. */
void
initialize_server_options(ServerOptions *options)
1999-10-27 11:42:43 +08:00
{
memset(options, 0, sizeof(*options));
/* Portable-specific options */
options->use_pam = -1;
/* Standard Options */
options->num_ports = 0;
options->ports_from_cmdline = 0;
options->queued_listen_addrs = NULL;
options->num_queued_listens = 0;
options->listen_addrs = NULL;
options->num_listen_addrs = 0;
options->address_family = -1;
options->routing_domain = NULL;
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/11/06 16:04:56 [channels.c channels.h clientloop.c nchan.c serverloop.c] [session.c ssh.c] agent forwarding and -R for ssh2, based on work from jhuuskon@messi.uku.fi - markus@cvs.openbsd.org 2000/11/06 16:13:27 [ssh.c sshconnect.c sshd.c] do not disabled rhosts(rsa) if server port > 1024; from pekkas@netcore.fi - markus@cvs.openbsd.org 2000/11/06 16:16:35 [sshconnect.c] downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net - markus@cvs.openbsd.org 2000/11/09 18:04:40 [auth1.c] typo; from mouring@pconline.com - markus@cvs.openbsd.org 2000/11/12 12:03:28 [ssh-agent.c] off-by-one when removing a key from the agent - markus@cvs.openbsd.org 2000/11/12 12:50:39 [auth-rh-rsa.c auth2.c authfd.c authfd.h] [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h] [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config] [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c] [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h] add support for RSA to SSH2. please test. there are now 3 types of keys: RSA1 is used by ssh-1 only, RSA and DSA are used by SSH2. you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA keys for SSH2 and use the RSA keys for hostkeys or for user keys. SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before. - (djm) Fix up Makefile and Redhat init script to create RSA host keys - (djm) Change to interim version
2000-11-13 19:57:25 +08:00
options->num_host_key_files = 0;
options->num_host_cert_files = 0;
options->host_key_agent = NULL;
options->pid_file = NULL;
options->login_grace_time = -1;
options->permit_root_login = PERMIT_NOT_SET;
options->ignore_rhosts = -1;
options->ignore_user_known_hosts = -1;
options->print_motd = -1;
options->print_lastlog = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->x11_use_localhost = -1;
options->permit_tty = -1;
options->permit_user_rc = -1;
options->xauth_location = NULL;
options->strict_modes = -1;
options->tcp_keep_alive = -1;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
options->hostbased_authentication = -1;
options->hostbased_uses_name_from_packet_only = -1;
options->hostbased_key_types = NULL;
options->hostkeyalgorithms = NULL;
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/11/06 16:04:56 [channels.c channels.h clientloop.c nchan.c serverloop.c] [session.c ssh.c] agent forwarding and -R for ssh2, based on work from jhuuskon@messi.uku.fi - markus@cvs.openbsd.org 2000/11/06 16:13:27 [ssh.c sshconnect.c sshd.c] do not disabled rhosts(rsa) if server port > 1024; from pekkas@netcore.fi - markus@cvs.openbsd.org 2000/11/06 16:16:35 [sshconnect.c] downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net - markus@cvs.openbsd.org 2000/11/09 18:04:40 [auth1.c] typo; from mouring@pconline.com - markus@cvs.openbsd.org 2000/11/12 12:03:28 [ssh-agent.c] off-by-one when removing a key from the agent - markus@cvs.openbsd.org 2000/11/12 12:50:39 [auth-rh-rsa.c auth2.c authfd.c authfd.h] [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h] [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config] [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c] [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h] add support for RSA to SSH2. please test. there are now 3 types of keys: RSA1 is used by ssh-1 only, RSA and DSA are used by SSH2. you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA keys for SSH2 and use the RSA keys for hostkeys or for user keys. SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before. - (djm) Fix up Makefile and Redhat init script to create RSA host keys - (djm) Change to interim version
2000-11-13 19:57:25 +08:00
options->pubkey_authentication = -1;
options->pubkey_key_types = NULL;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
options->gss_authentication=-1;
options->gss_cleanup_creds = -1;
options->gss_strict_acceptor = -1;
options->password_authentication = -1;
- (djm) Big OpenBSD sync: - markus@cvs.openbsd.org 2000/09/30 10:27:44 [log.c] allow loglevel debug - markus@cvs.openbsd.org 2000/10/03 11:59:57 [packet.c] hmac->mac - markus@cvs.openbsd.org 2000/10/03 12:03:03 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] move fake-auth from auth1.c to individual auth methods, disables s/key in debug-msg - markus@cvs.openbsd.org 2000/10/03 12:16:48 ssh.c do not resolve canonname, i have no idea why this was added oin ossh - markus@cvs.openbsd.org 2000/10/09 15:30:44 ssh-keygen.1 ssh-keygen.c -X now reads private ssh.com DSA keys, too. - markus@cvs.openbsd.org 2000/10/09 15:32:34 auth-options.c clear options on every call. - markus@cvs.openbsd.org 2000/10/09 15:51:00 authfd.c authfd.h interop with ssh-agent2, from <res@shore.net> - markus@cvs.openbsd.org 2000/10/10 14:20:45 compat.c use rexexp for version string matching - provos@cvs.openbsd.org 2000/10/10 22:02:18 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] First rough implementation of the diffie-hellman group exchange. The client can ask the server for bigger groups to perform the diffie-hellman in, thus increasing the attack complexity when using ciphers with longer keys. University of Windsor provided network, T the company. - markus@cvs.openbsd.org 2000/10/11 13:59:52 [auth-rsa.c auth2.c] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:00:27 [auth-options.h] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:03:27 [scp.1 scp.c] support 'scp -o' with help from mouring@pconline.com - markus@cvs.openbsd.org 2000/10/11 14:11:35 [dh.c] Wall - markus@cvs.openbsd.org 2000/10/11 14:14:40 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me - markus@cvs.openbsd.org 2000/10/11 14:27:24 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] [sshconnect2.c sshd.c] new cipher framework - markus@cvs.openbsd.org 2000/10/11 14:45:21 [cipher.c] remove DES - markus@cvs.openbsd.org 2000/10/12 03:59:20 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] enable DES in SSH-1 clients only - markus@cvs.openbsd.org 2000/10/12 08:21:13 [kex.h packet.c] remove unused - markus@cvs.openbsd.org 2000/10/13 12:34:46 [sshd.c] Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - markus@cvs.openbsd.org 2000/10/13 12:59:15 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] rijndael/aes support - markus@cvs.openbsd.org 2000/10/13 13:10:54 [sshd.8] more info about -V - markus@cvs.openbsd.org 2000/10/13 13:12:02 [myproposal.h] prefer no compression
2000-10-14 13:23:11 +08:00
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->permit_user_env = -1;
options->compression = -1;
options->rekey_limit = -1;
options->rekey_interval = -1;
options->allow_tcp_forwarding = -1;
options->allow_streamlocal_forwarding = -1;
options->allow_agent_forwarding = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
options->num_allow_groups = 0;
options->num_deny_groups = 0;
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
options->num_subsystems = 0;
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1;
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
options->use_dns = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
options->num_authkeys_files = 0;
options->num_accept_env = 0;
options->permit_tun = -1;
options->permitted_opens = NULL;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
options->authorized_keys_command = NULL;
options->authorized_keys_command_user = NULL;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
options->authorized_principals_command = NULL;
options->authorized_principals_command_user = NULL;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->fingerprint_hash = -1;
options->disable_forwarding = -1;
options->expose_userauth_info = -1;
1999-10-27 11:42:43 +08:00
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
static int
option_clear_or_none(const char *o)
{
return o == NULL || strcasecmp(o, "none") == 0;
}
static void
assemble_algorithms(ServerOptions *o)
{
if (kex_assemble_names(KEX_SERVER_ENCRYPT, &o->ciphers) != 0 ||
kex_assemble_names(KEX_SERVER_MAC, &o->macs) != 0 ||
kex_assemble_names(KEX_SERVER_KEX, &o->kex_algorithms) != 0 ||
kex_assemble_names(KEX_DEFAULT_PK_ALG,
&o->hostkeyalgorithms) != 0 ||
kex_assemble_names(KEX_DEFAULT_PK_ALG,
&o->hostbased_key_types) != 0 ||
kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->pubkey_key_types) != 0)
fatal("kex_assemble_names failed");
}
static void
array_append(const char *file, const int line, const char *directive,
char ***array, u_int *lp, const char *s)
{
if (*lp >= INT_MAX)
fatal("%s line %d: Too many %s entries", file, line, directive);
*array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array));
(*array)[*lp] = xstrdup(s);
(*lp)++;
}
void
servconf_add_hostkey(const char *file, const int line,
ServerOptions *options, const char *path)
{
char *apath = derelativise_path(path);
array_append(file, line, "HostKey",
&options->host_key_files, &options->num_host_key_files, apath);
free(apath);
}
void
servconf_add_hostcert(const char *file, const int line,
ServerOptions *options, const char *path)
{
char *apath = derelativise_path(path);
array_append(file, line, "HostCertificate",
&options->host_cert_files, &options->num_host_cert_files, apath);
free(apath);
}
void
fill_default_server_options(ServerOptions *options)
1999-10-27 11:42:43 +08:00
{
u_int i;
/* Portable-specific options */
if (options->use_pam == -1)
options->use_pam = 0;
/* Standard Options */
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/11/06 16:04:56 [channels.c channels.h clientloop.c nchan.c serverloop.c] [session.c ssh.c] agent forwarding and -R for ssh2, based on work from jhuuskon@messi.uku.fi - markus@cvs.openbsd.org 2000/11/06 16:13:27 [ssh.c sshconnect.c sshd.c] do not disabled rhosts(rsa) if server port > 1024; from pekkas@netcore.fi - markus@cvs.openbsd.org 2000/11/06 16:16:35 [sshconnect.c] downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net - markus@cvs.openbsd.org 2000/11/09 18:04:40 [auth1.c] typo; from mouring@pconline.com - markus@cvs.openbsd.org 2000/11/12 12:03:28 [ssh-agent.c] off-by-one when removing a key from the agent - markus@cvs.openbsd.org 2000/11/12 12:50:39 [auth-rh-rsa.c auth2.c authfd.c authfd.h] [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h] [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config] [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c] [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h] add support for RSA to SSH2. please test. there are now 3 types of keys: RSA1 is used by ssh-1 only, RSA and DSA are used by SSH2. you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA keys for SSH2 and use the RSA keys for hostkeys or for user keys. SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before. - (djm) Fix up Makefile and Redhat init script to create RSA host keys - (djm) Change to interim version
2000-11-13 19:57:25 +08:00
if (options->num_host_key_files == 0) {
/* fill default hostkeys for protocols */
servconf_add_hostkey("[default]", 0, options,
_PATH_HOST_RSA_KEY_FILE);
servconf_add_hostkey("[default]", 0, options,
_PATH_HOST_DSA_KEY_FILE);
#ifdef OPENSSL_HAS_ECC
servconf_add_hostkey("[default]", 0, options,
_PATH_HOST_ECDSA_KEY_FILE);
#endif
servconf_add_hostkey("[default]", 0, options,
_PATH_HOST_ED25519_KEY_FILE);
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/11/06 16:04:56 [channels.c channels.h clientloop.c nchan.c serverloop.c] [session.c ssh.c] agent forwarding and -R for ssh2, based on work from jhuuskon@messi.uku.fi - markus@cvs.openbsd.org 2000/11/06 16:13:27 [ssh.c sshconnect.c sshd.c] do not disabled rhosts(rsa) if server port > 1024; from pekkas@netcore.fi - markus@cvs.openbsd.org 2000/11/06 16:16:35 [sshconnect.c] downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net - markus@cvs.openbsd.org 2000/11/09 18:04:40 [auth1.c] typo; from mouring@pconline.com - markus@cvs.openbsd.org 2000/11/12 12:03:28 [ssh-agent.c] off-by-one when removing a key from the agent - markus@cvs.openbsd.org 2000/11/12 12:50:39 [auth-rh-rsa.c auth2.c authfd.c authfd.h] [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h] [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config] [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c] [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h] add support for RSA to SSH2. please test. there are now 3 types of keys: RSA1 is used by ssh-1 only, RSA and DSA are used by SSH2. you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA keys for SSH2 and use the RSA keys for hostkeys or for user keys. SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before. - (djm) Fix up Makefile and Redhat init script to create RSA host keys - (djm) Change to interim version
2000-11-13 19:57:25 +08:00
}
/* No certificates by default */
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->address_family == -1)
options->address_family = AF_UNSPEC;
if (options->listen_addrs == NULL)
add_listen_addr(options, NULL, NULL, 0);
if (options->pid_file == NULL)
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
if (options->login_grace_time == -1)
options->login_grace_time = 120;
if (options->permit_root_login == PERMIT_NOT_SET)
options->permit_root_login = PERMIT_NO_PASSWD;
if (options->ignore_rhosts == -1)
- OpenBSD CVS updates to v1.2.3 [ssh.h atomicio.c] - int atomicio -> ssize_t (for alpha). ok deraadt@ [auth-rsa.c] - delay MD5 computation until client sends response, free() early, cleanup. [cipher.c] - void* -> unsigned char*, ok niels@ [hostfile.c] - remove unused variable 'len'. fix comments. - remove unused variable [log-client.c log-server.c] - rename a cpp symbol, to avoid param.h collision [packet.c] - missing xfree() - getsockname() requires initialized tolen; andy@guildsoftware.com - use getpeername() in packet_connection_is_on_socket(), fixes sshd -i; from Holger.Trapp@Informatik.TU-Chemnitz.DE [pty.c pty.h] - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ [readconf.c] - turn off x11-fwd for the client, too. [rsa.c] - PKCS#1 padding [scp.c] - allow '.' in usernames; from jedgar@fxp.org [servconf.c] - typo: ignore_user_known_hosts int->flag; naddy@mips.rhein-neckar.de - sync with sshd_config [ssh-keygen.c] - enable ssh-keygen -l -f ~/.ssh/known_hosts, ok deraadt@ [ssh.1] - Change invalid 'CHAT' loglevel to 'VERBOSE' [ssh.c] - suppress AAAA query host when '-4' is used; from shin@nd.net.fujitsu.co.jp - turn off x11-fwd for the client, too. [sshconnect.c] - missing xfree() - retry rresvport_af(), too. from sumikawa@ebina.hitachi.co.jp. - read error vs. "Connection closed by remote host" [sshd.8] - ie. -> i.e., - do not link to a commercial page.. - sync with sshd_config [sshd.c] - no need for poll.h; from bright@wintelcom.net - log with level log() not fatal() if peer behaves badly. - don't panic if client behaves strange. ok deraadt@ - make no-port-forwarding for RSA keys deny both -L and -R style fwding - delay close() of pty until the pty has been chowned back to root - oops, fix comment, too. - missing xfree() - move XAUTHORITY to subdir. ok dugsong@. fixes debian bug #57907, too. (http://cgi.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=57907) - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ - create x11 cookie file - fix pr 1113, fclose() -> pclose(), todo: remote popen() - version 1.2.3 - Cleaned up
2000-03-09 18:27:49 +08:00
options->ignore_rhosts = 1;
if (options->ignore_user_known_hosts == -1)
options->ignore_user_known_hosts = 0;
if (options->print_motd == -1)
options->print_motd = 1;
if (options->print_lastlog == -1)
options->print_lastlog = 1;
if (options->x11_forwarding == -1)
- OpenBSD CVS updates to v1.2.3 [ssh.h atomicio.c] - int atomicio -> ssize_t (for alpha). ok deraadt@ [auth-rsa.c] - delay MD5 computation until client sends response, free() early, cleanup. [cipher.c] - void* -> unsigned char*, ok niels@ [hostfile.c] - remove unused variable 'len'. fix comments. - remove unused variable [log-client.c log-server.c] - rename a cpp symbol, to avoid param.h collision [packet.c] - missing xfree() - getsockname() requires initialized tolen; andy@guildsoftware.com - use getpeername() in packet_connection_is_on_socket(), fixes sshd -i; from Holger.Trapp@Informatik.TU-Chemnitz.DE [pty.c pty.h] - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ [readconf.c] - turn off x11-fwd for the client, too. [rsa.c] - PKCS#1 padding [scp.c] - allow '.' in usernames; from jedgar@fxp.org [servconf.c] - typo: ignore_user_known_hosts int->flag; naddy@mips.rhein-neckar.de - sync with sshd_config [ssh-keygen.c] - enable ssh-keygen -l -f ~/.ssh/known_hosts, ok deraadt@ [ssh.1] - Change invalid 'CHAT' loglevel to 'VERBOSE' [ssh.c] - suppress AAAA query host when '-4' is used; from shin@nd.net.fujitsu.co.jp - turn off x11-fwd for the client, too. [sshconnect.c] - missing xfree() - retry rresvport_af(), too. from sumikawa@ebina.hitachi.co.jp. - read error vs. "Connection closed by remote host" [sshd.8] - ie. -> i.e., - do not link to a commercial page.. - sync with sshd_config [sshd.c] - no need for poll.h; from bright@wintelcom.net - log with level log() not fatal() if peer behaves badly. - don't panic if client behaves strange. ok deraadt@ - make no-port-forwarding for RSA keys deny both -L and -R style fwding - delay close() of pty until the pty has been chowned back to root - oops, fix comment, too. - missing xfree() - move XAUTHORITY to subdir. ok dugsong@. fixes debian bug #57907, too. (http://cgi.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=57907) - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ - create x11 cookie file - fix pr 1113, fclose() -> pclose(), todo: remote popen() - version 1.2.3 - Cleaned up
2000-03-09 18:27:49 +08:00
options->x11_forwarding = 0;
if (options->x11_display_offset == -1)
- OpenBSD CVS updates to v1.2.3 [ssh.h atomicio.c] - int atomicio -> ssize_t (for alpha). ok deraadt@ [auth-rsa.c] - delay MD5 computation until client sends response, free() early, cleanup. [cipher.c] - void* -> unsigned char*, ok niels@ [hostfile.c] - remove unused variable 'len'. fix comments. - remove unused variable [log-client.c log-server.c] - rename a cpp symbol, to avoid param.h collision [packet.c] - missing xfree() - getsockname() requires initialized tolen; andy@guildsoftware.com - use getpeername() in packet_connection_is_on_socket(), fixes sshd -i; from Holger.Trapp@Informatik.TU-Chemnitz.DE [pty.c pty.h] - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ [readconf.c] - turn off x11-fwd for the client, too. [rsa.c] - PKCS#1 padding [scp.c] - allow '.' in usernames; from jedgar@fxp.org [servconf.c] - typo: ignore_user_known_hosts int->flag; naddy@mips.rhein-neckar.de - sync with sshd_config [ssh-keygen.c] - enable ssh-keygen -l -f ~/.ssh/known_hosts, ok deraadt@ [ssh.1] - Change invalid 'CHAT' loglevel to 'VERBOSE' [ssh.c] - suppress AAAA query host when '-4' is used; from shin@nd.net.fujitsu.co.jp - turn off x11-fwd for the client, too. [sshconnect.c] - missing xfree() - retry rresvport_af(), too. from sumikawa@ebina.hitachi.co.jp. - read error vs. "Connection closed by remote host" [sshd.8] - ie. -> i.e., - do not link to a commercial page.. - sync with sshd_config [sshd.c] - no need for poll.h; from bright@wintelcom.net - log with level log() not fatal() if peer behaves badly. - don't panic if client behaves strange. ok deraadt@ - make no-port-forwarding for RSA keys deny both -L and -R style fwding - delay close() of pty until the pty has been chowned back to root - oops, fix comment, too. - missing xfree() - move XAUTHORITY to subdir. ok dugsong@. fixes debian bug #57907, too. (http://cgi.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=57907) - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ - create x11 cookie file - fix pr 1113, fclose() -> pclose(), todo: remote popen() - version 1.2.3 - Cleaned up
2000-03-09 18:27:49 +08:00
options->x11_display_offset = 10;
if (options->x11_use_localhost == -1)
options->x11_use_localhost = 1;
if (options->xauth_location == NULL)
options->xauth_location = xstrdup(_PATH_XAUTH);
if (options->permit_tty == -1)
options->permit_tty = 1;
if (options->permit_user_rc == -1)
options->permit_user_rc = 1;
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->tcp_keep_alive == -1)
options->tcp_keep_alive = 1;
if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->hostbased_uses_name_from_packet_only == -1)
options->hostbased_uses_name_from_packet_only = 0;
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/11/06 16:04:56 [channels.c channels.h clientloop.c nchan.c serverloop.c] [session.c ssh.c] agent forwarding and -R for ssh2, based on work from jhuuskon@messi.uku.fi - markus@cvs.openbsd.org 2000/11/06 16:13:27 [ssh.c sshconnect.c sshd.c] do not disabled rhosts(rsa) if server port > 1024; from pekkas@netcore.fi - markus@cvs.openbsd.org 2000/11/06 16:16:35 [sshconnect.c] downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net - markus@cvs.openbsd.org 2000/11/09 18:04:40 [auth1.c] typo; from mouring@pconline.com - markus@cvs.openbsd.org 2000/11/12 12:03:28 [ssh-agent.c] off-by-one when removing a key from the agent - markus@cvs.openbsd.org 2000/11/12 12:50:39 [auth-rh-rsa.c auth2.c authfd.c authfd.h] [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h] [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config] [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c] [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h] add support for RSA to SSH2. please test. there are now 3 types of keys: RSA1 is used by ssh-1 only, RSA and DSA are used by SSH2. you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA keys for SSH2 and use the RSA keys for hostkeys or for user keys. SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before. - (djm) Fix up Makefile and Redhat init script to create RSA host keys - (djm) Change to interim version
2000-11-13 19:57:25 +08:00
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->kerberos_authentication == -1)
options->kerberos_authentication = 0;
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
if (options->kerberos_get_afs_token == -1)
options->kerberos_get_afs_token = 0;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_cleanup_creds == -1)
options->gss_cleanup_creds = 1;
if (options->gss_strict_acceptor == -1)
options->gss_strict_acceptor = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
- (djm) Big OpenBSD sync: - markus@cvs.openbsd.org 2000/09/30 10:27:44 [log.c] allow loglevel debug - markus@cvs.openbsd.org 2000/10/03 11:59:57 [packet.c] hmac->mac - markus@cvs.openbsd.org 2000/10/03 12:03:03 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] move fake-auth from auth1.c to individual auth methods, disables s/key in debug-msg - markus@cvs.openbsd.org 2000/10/03 12:16:48 ssh.c do not resolve canonname, i have no idea why this was added oin ossh - markus@cvs.openbsd.org 2000/10/09 15:30:44 ssh-keygen.1 ssh-keygen.c -X now reads private ssh.com DSA keys, too. - markus@cvs.openbsd.org 2000/10/09 15:32:34 auth-options.c clear options on every call. - markus@cvs.openbsd.org 2000/10/09 15:51:00 authfd.c authfd.h interop with ssh-agent2, from <res@shore.net> - markus@cvs.openbsd.org 2000/10/10 14:20:45 compat.c use rexexp for version string matching - provos@cvs.openbsd.org 2000/10/10 22:02:18 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] First rough implementation of the diffie-hellman group exchange. The client can ask the server for bigger groups to perform the diffie-hellman in, thus increasing the attack complexity when using ciphers with longer keys. University of Windsor provided network, T the company. - markus@cvs.openbsd.org 2000/10/11 13:59:52 [auth-rsa.c auth2.c] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:00:27 [auth-options.h] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:03:27 [scp.1 scp.c] support 'scp -o' with help from mouring@pconline.com - markus@cvs.openbsd.org 2000/10/11 14:11:35 [dh.c] Wall - markus@cvs.openbsd.org 2000/10/11 14:14:40 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me - markus@cvs.openbsd.org 2000/10/11 14:27:24 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] [sshconnect2.c sshd.c] new cipher framework - markus@cvs.openbsd.org 2000/10/11 14:45:21 [cipher.c] remove DES - markus@cvs.openbsd.org 2000/10/12 03:59:20 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] enable DES in SSH-1 clients only - markus@cvs.openbsd.org 2000/10/12 08:21:13 [kex.h packet.c] remove unused - markus@cvs.openbsd.org 2000/10/13 12:34:46 [sshd.c] Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - markus@cvs.openbsd.org 2000/10/13 12:59:15 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] rijndael/aes support - markus@cvs.openbsd.org 2000/10/13 13:10:54 [sshd.8] more info about -V - markus@cvs.openbsd.org 2000/10/13 13:12:02 [myproposal.h] prefer no compression
2000-10-14 13:23:11 +08:00
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 0;
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
if (options->permit_empty_passwd == -1)
- OpenBSD CVS updates to v1.2.3 [ssh.h atomicio.c] - int atomicio -> ssize_t (for alpha). ok deraadt@ [auth-rsa.c] - delay MD5 computation until client sends response, free() early, cleanup. [cipher.c] - void* -> unsigned char*, ok niels@ [hostfile.c] - remove unused variable 'len'. fix comments. - remove unused variable [log-client.c log-server.c] - rename a cpp symbol, to avoid param.h collision [packet.c] - missing xfree() - getsockname() requires initialized tolen; andy@guildsoftware.com - use getpeername() in packet_connection_is_on_socket(), fixes sshd -i; from Holger.Trapp@Informatik.TU-Chemnitz.DE [pty.c pty.h] - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ [readconf.c] - turn off x11-fwd for the client, too. [rsa.c] - PKCS#1 padding [scp.c] - allow '.' in usernames; from jedgar@fxp.org [servconf.c] - typo: ignore_user_known_hosts int->flag; naddy@mips.rhein-neckar.de - sync with sshd_config [ssh-keygen.c] - enable ssh-keygen -l -f ~/.ssh/known_hosts, ok deraadt@ [ssh.1] - Change invalid 'CHAT' loglevel to 'VERBOSE' [ssh.c] - suppress AAAA query host when '-4' is used; from shin@nd.net.fujitsu.co.jp - turn off x11-fwd for the client, too. [sshconnect.c] - missing xfree() - retry rresvport_af(), too. from sumikawa@ebina.hitachi.co.jp. - read error vs. "Connection closed by remote host" [sshd.8] - ie. -> i.e., - do not link to a commercial page.. - sync with sshd_config [sshd.c] - no need for poll.h; from bright@wintelcom.net - log with level log() not fatal() if peer behaves badly. - don't panic if client behaves strange. ok deraadt@ - make no-port-forwarding for RSA keys deny both -L and -R style fwding - delay close() of pty until the pty has been chowned back to root - oops, fix comment, too. - missing xfree() - move XAUTHORITY to subdir. ok dugsong@. fixes debian bug #57907, too. (http://cgi.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=57907) - register cleanup for pty earlier. move code for pty-owner handling to pty.c ok provos@, dugsong@ - create x11 cookie file - fix pr 1113, fclose() -> pclose(), todo: remote popen() - version 1.2.3 - Cleaned up
2000-03-09 18:27:49 +08:00
options->permit_empty_passwd = 0;
if (options->permit_user_env == -1)
options->permit_user_env = 0;
if (options->compression == -1)
options->compression = COMP_DELAYED;
if (options->rekey_limit == -1)
options->rekey_limit = 0;
if (options->rekey_interval == -1)
options->rekey_interval = 0;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = FORWARD_ALLOW;
if (options->allow_streamlocal_forwarding == -1)
options->allow_streamlocal_forwarding = FORWARD_ALLOW;
if (options->allow_agent_forwarding == -1)
options->allow_agent_forwarding = 1;
if (options->fwd_opts.gateway_ports == -1)
options->fwd_opts.gateway_ports = 0;
if (options->max_startups == -1)
options->max_startups = 100;
if (options->max_startups_rate == -1)
options->max_startups_rate = 30; /* 30% */
if (options->max_startups_begin == -1)
options->max_startups_begin = 10;
if (options->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
options->max_sessions = DEFAULT_SESSIONS_MAX;
if (options->use_dns == -1)
options->use_dns = 0;
if (options->client_alive_interval == -1)
options->client_alive_interval = 0;
if (options->client_alive_count_max == -1)
options->client_alive_count_max = 3;
if (options->num_authkeys_files == 0) {
array_append("[default]", 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS);
array_append("[default]", 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS2);
}
if (options->permit_tun == -1)
options->permit_tun = SSH_TUNMODE_NO;
if (options->ip_qos_interactive == -1)
options->ip_qos_interactive = IPTOS_LOWDELAY;
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_THROUGHPUT;
if (options->version_addendum == NULL)
options->version_addendum = xstrdup("");
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
if (options->disable_forwarding == -1)
options->disable_forwarding = 0;
if (options->expose_userauth_info == -1)
options->expose_userauth_info = 0;
assemble_algorithms(options);
/* Turn privilege separation and sandboxing on by default */
if (use_privsep == -1)
use_privsep = PRIVSEP_ON;
#define CLEAR_ON_NONE(v) \
do { \
if (option_clear_or_none(v)) { \
free(v); \
v = NULL; \
} \
} while(0)
CLEAR_ON_NONE(options->pid_file);
CLEAR_ON_NONE(options->xauth_location);
CLEAR_ON_NONE(options->banner);
CLEAR_ON_NONE(options->trusted_user_ca_keys);
CLEAR_ON_NONE(options->revoked_keys_file);
CLEAR_ON_NONE(options->authorized_principals_file);
CLEAR_ON_NONE(options->adm_forced_command);
CLEAR_ON_NONE(options->chroot_directory);
CLEAR_ON_NONE(options->routing_domain);
for (i = 0; i < options->num_host_key_files; i++)
CLEAR_ON_NONE(options->host_key_files[i]);
for (i = 0; i < options->num_host_cert_files; i++)
CLEAR_ON_NONE(options->host_cert_files[i]);
#undef CLEAR_ON_NONE
/* Similar handling for AuthenticationMethods=any */
if (options->num_auth_methods == 1 &&
strcmp(options->auth_methods[0], "any") == 0) {
free(options->auth_methods[0]);
options->auth_methods[0] = NULL;
options->num_auth_methods = 0;
}
#ifndef HAVE_MMAP
if (use_privsep && options->compression == 1) {
error("This platform does not support both privilege "
"separation and compression");
error("Compression disabled");
options->compression = 0;
}
#endif
1999-10-27 11:42:43 +08:00
}
/* Keyword tokens. */
typedef enum {
sBadOption, /* == unknown option */
/* Portable-specific options */
sUsePAM,
/* Standard Options */
sPort, sHostKeyFile, sLoginGraceTime,
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
sKerberosGetAFSToken,
sKerberosTgtPassing, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
sKexAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
sExposeAuthInfo, sRDomain,
sDeprecated, sIgnore, sUnsupported
1999-10-27 11:42:43 +08:00
} ServerOpCodes;
#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
1999-10-27 11:42:43 +08:00
/* Textual representation of the tokens. */
static struct {
const char *name;
ServerOpCodes opcode;
u_int flags;
} keywords[] = {
/* Portable-specific options */
#ifdef USE_PAM
{ "usepam", sUsePAM, SSHCFG_GLOBAL },
#else
{ "usepam", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
/* Standard Options */
{ "port", sPort, SSHCFG_GLOBAL },
{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
{ "pidfile", sPidFile, SSHCFG_GLOBAL },
{ "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
{ "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
{ "loglevel", sLogLevel, SSHCFG_ALL },
{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
{ "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
{ "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL },
{ "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
{ "rsaauthentication", sDeprecated, SSHCFG_ALL },
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
{ "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
#ifdef KRB5
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
#ifdef USE_AFS
{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
#else
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
#ifdef DISABLE_LASTLOG
{ "printlastlog", sUnsupported, SSHCFG_GLOBAL },
#else
{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
#endif
{ "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
{ "uselogin", sDeprecated, SSHCFG_GLOBAL },
{ "compression", sCompression, SSHCFG_GLOBAL },
{ "rekeylimit", sRekeyLimit, SSHCFG_ALL },
{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
{ "allowusers", sAllowUsers, SSHCFG_ALL },
{ "denyusers", sDenyUsers, SSHCFG_ALL },
{ "allowgroups", sAllowGroups, SSHCFG_ALL },
{ "denygroups", sDenyGroups, SSHCFG_ALL },
{ "ciphers", sCiphers, SSHCFG_GLOBAL },
{ "macs", sMacs, SSHCFG_GLOBAL },
{ "protocol", sIgnore, SSHCFG_GLOBAL },
{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
{ "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
{ "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
{ "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
{ "permittty", sPermitTTY, SSHCFG_ALL },
{ "permituserrc", sPermitUserRC, SSHCFG_ALL },
{ "match", sMatch, SSHCFG_ALL },
{ "permitopen", sPermitOpen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL },
{ "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
{ "rdomain", sRDomain, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
1999-10-27 11:42:43 +08:00
};
static struct {
int val;
char *text;
} tunmode_desc[] = {
{ SSH_TUNMODE_NO, "no" },
{ SSH_TUNMODE_POINTOPOINT, "point-to-point" },
{ SSH_TUNMODE_ETHERNET, "ethernet" },
{ SSH_TUNMODE_YES, "yes" },
{ -1, NULL }
};
/*
* Returns the number of the token pointed to by cp or sBadOption.
*/
1999-10-27 11:42:43 +08:00
static ServerOpCodes
parse_token(const char *cp, const char *filename,
int linenum, u_int *flags)
1999-10-27 11:42:43 +08:00
{
u_int i;
1999-10-27 11:42:43 +08:00
for (i = 0; keywords[i].name; i++)
if (strcasecmp(cp, keywords[i].name) == 0) {
*flags = keywords[i].flags;
return keywords[i].opcode;
}
1999-10-27 11:42:43 +08:00
error("%s: line %d: Bad configuration option: %s",
filename, linenum, cp);
return sBadOption;
1999-10-27 11:42:43 +08:00
}
char *
derelativise_path(const char *path)
{
char *expanded, *ret, cwd[PATH_MAX];
if (strcasecmp(path, "none") == 0)
return xstrdup("none");
expanded = tilde_expand_filename(path, getuid());
if (*expanded == '/')
return expanded;
if (getcwd(cwd, sizeof(cwd)) == NULL)
fatal("%s: getcwd: %s", __func__, strerror(errno));
xasprintf(&ret, "%s/%s", cwd, expanded);
free(expanded);
return ret;
}
static void
add_listen_addr(ServerOptions *options, const char *addr,
const char *rdomain, int port)
{
u_int i;
if (port > 0)
add_one_listen_addr(options, addr, rdomain, port);
else {
for (i = 0; i < options->num_ports; i++) {
add_one_listen_addr(options, addr, rdomain,
options->ports[i]);
}
}
}
static void
add_one_listen_addr(ServerOptions *options, const char *addr,
const char *rdomain, int port)
{
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr;
u_int i;
/* Find listen_addrs entry for this rdomain */
for (i = 0; i < options->num_listen_addrs; i++) {
if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
break;
if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
continue;
if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
break;
}
if (i >= options->num_listen_addrs) {
/* No entry for this rdomain; allocate one */
if (i >= INT_MAX)
fatal("%s: too many listen addresses", __func__);
options->listen_addrs = xrecallocarray(options->listen_addrs,
options->num_listen_addrs, options->num_listen_addrs + 1,
sizeof(*options->listen_addrs));
i = options->num_listen_addrs++;
if (rdomain != NULL)
options->listen_addrs[i].rdomain = xstrdup(rdomain);
}
/* options->listen_addrs[i] points to the addresses for this rdomain */
memset(&hints, 0, sizeof(hints));
hints.ai_family = options->address_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
fatal("bad addr or host: %s (%s)",
addr ? addr : "<NULL>",
ssh_gai_strerror(gaierr));
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
;
ai->ai_next = options->listen_addrs[i].addrs;
options->listen_addrs[i].addrs = aitop;
}
/* Returns nonzero if the routing domain name is valid */
static int
valid_rdomain(const char *name)
{
const char *errstr;
long long num;
struct rt_tableinfo info;
int mib[6];
size_t miblen = sizeof(mib);
if (name == NULL)
return 1;
num = strtonum(name, 0, 255, &errstr);
if (errstr != NULL)
return 0;
/* Check whether the table actually exists */
memset(mib, 0, sizeof(mib));
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[4] = NET_RT_TABLE;
mib[5] = (int)num;
if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
return 0;
return 1;
}
/*
* Queue a ListenAddress to be processed once we have all of the Ports
* and AddressFamily options.
*/
static void
queue_listen_addr(ServerOptions *options, const char *addr,
const char *rdomain, int port)
{
struct queued_listenaddr *qla;
options->queued_listen_addrs = xrecallocarray(
options->queued_listen_addrs,
options->num_queued_listens, options->num_queued_listens + 1,
sizeof(*options->queued_listen_addrs));
qla = &options->queued_listen_addrs[options->num_queued_listens++];
qla->addr = xstrdup(addr);
qla->port = port;
qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
}
/*
* Process queued (text) ListenAddress entries.
*/
static void
process_queued_listen_addrs(ServerOptions *options)
{
u_int i;
struct queued_listenaddr *qla;
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->address_family == -1)
options->address_family = AF_UNSPEC;
for (i = 0; i < options->num_queued_listens; i++) {
qla = &options->queued_listen_addrs[i];
add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
free(qla->addr);
free(qla->rdomain);
}
free(options->queued_listen_addrs);
options->queued_listen_addrs = NULL;
options->num_queued_listens = 0;
}
/*
* Inform channels layer of permitopen options from configuration.
*/
void
process_permitopen(struct ssh *ssh, ServerOptions *options)
{
u_int i;
int port;
char *host, *arg, *oarg;
channel_clear_adm_permitted_opens(ssh);
if (options->num_permitted_opens == 0)
return; /* permit any */
/* handle keywords: "any" / "none" */
if (options->num_permitted_opens == 1 &&
strcmp(options->permitted_opens[0], "any") == 0)
return;
if (options->num_permitted_opens == 1 &&
strcmp(options->permitted_opens[0], "none") == 0) {
channel_disable_adm_local_opens(ssh);
return;
}
/* Otherwise treat it as a list of permitted host:port */
for (i = 0; i < options->num_permitted_opens; i++) {
oarg = arg = xstrdup(options->permitted_opens[i]);
host = hpdelim(&arg);
if (host == NULL)
fatal("%s: missing host in PermitOpen", __func__);
host = cleanhostname(host);
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
fatal("%s: bad port number in PermitOpen", __func__);
/* Send it to channels layer */
channel_add_adm_permitted_opens(ssh, host, port);
free(oarg);
}
}
struct connection_info *
get_connection_info(int populate, int use_dns)
{
struct ssh *ssh = active_state; /* XXX */
static struct connection_info ci;
if (!populate)
return &ci;
ci.host = auth_get_canonical_hostname(ssh, use_dns);
ci.address = ssh_remote_ipaddr(ssh);
ci.laddress = ssh_local_ipaddr(ssh);
ci.lport = ssh_local_port(ssh);
ci.rdomain = ssh_packet_rdomain_in(ssh);
return &ci;
}
/*
* The strategy for the Match blocks is that the config file is parsed twice.
*
* The first time is at startup. activep is initialized to 1 and the
* directives in the global context are processed and acted on. Hitting a
* Match directive unsets activep and the directives inside the block are
* checked for syntax only.
*
* The second time is after a connection has been established but before
* authentication. activep is initialized to 2 and global config directives
* are ignored since they have already been processed. If the criteria in a
* Match block is met, activep is set and the subsequent directives
* processed and actioned until EOF or another Match block unsets it. Any
* options set are copied into the main server config.
*
* Potential additions/improvements:
* - Add Match support for pre-kex directives, eg. Ciphers.
*
* - Add a Tag directive (idea from David Leonard) ala pf, eg:
* Match Address 192.168.0.*
* Tag trusted
* Match Group wheel
* Tag trusted
* Match Tag trusted
* AllowTcpForwarding yes
* GatewayPorts clientspecified
* [...]
*
* - Add a PermittedChannelRequests directive
* Match Group shell
* PermittedChannelRequests session,forwarded-tcpip
*/
static int
match_cfg_line_group(const char *grps, int line, const char *user)
{
int result = 0;
struct passwd *pw;
if (user == NULL)
goto out;
if ((pw = getpwnam(user)) == NULL) {
debug("Can't match group at line %d because user %.100s does "
"not exist", line, user);
} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
debug("Can't Match group because user %.100s not in any group "
"at line %d", user, line);
} else if (ga_match_pattern_list(grps) != 1) {
debug("user %.100s does not match group list %.100s at line %d",
user, grps, line);
} else {
debug("user %.100s matched group list %.100s at line %d", user,
grps, line);
result = 1;
}
out:
ga_free();
return result;
}
/*
* All of the attributes on a single Match line are ANDed together, so we need
* to check every attribute and set the result to zero if any attribute does
* not match.
*/
static int
match_cfg_line(char **condition, int line, struct connection_info *ci)
{
int result = 1, attributes = 0, port;
char *arg, *attrib, *cp = *condition;
if (ci == NULL)
debug3("checking syntax for 'Match %s'", cp);
else
debug3("checking match for '%s' user %s host %s addr %s "
"laddr %s lport %d", cp, ci->user ? ci->user : "(null)",
ci->host ? ci->host : "(null)",
ci->address ? ci->address : "(null)",
ci->laddress ? ci->laddress : "(null)", ci->lport);
while ((attrib = strdelim(&cp)) && *attrib != '\0') {
attributes++;
if (strcasecmp(attrib, "all") == 0) {
if (attributes != 1 ||
((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
error("'all' cannot be combined with other "
"Match attributes");
return -1;
}
*condition = cp;
return 1;
}
if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
error("Missing Match criteria for %s", attrib);
return -1;
}
if (strcasecmp(attrib, "user") == 0) {
if (ci == NULL || ci->user == NULL) {
result = 0;
continue;
}
if (match_pattern_list(ci->user, arg, 0) != 1)
result = 0;
else
debug("user %.100s matched 'User %.100s' at "
"line %d", ci->user, arg, line);
} else if (strcasecmp(attrib, "group") == 0) {
if (ci == NULL || ci->user == NULL) {
result = 0;
continue;
}
switch (match_cfg_line_group(arg, line, ci->user)) {
case -1:
return -1;
case 0:
result = 0;
}
} else if (strcasecmp(attrib, "host") == 0) {
if (ci == NULL || ci->host == NULL) {
result = 0;
continue;
}
if (match_hostname(ci->host, arg) != 1)
result = 0;
else
debug("connection from %.100s matched 'Host "
"%.100s' at line %d", ci->host, arg, line);
} else if (strcasecmp(attrib, "address") == 0) {
if (ci == NULL || ci->address == NULL) {
result = 0;
continue;
}
switch (addr_match_list(ci->address, arg)) {
case 1:
debug("connection from %.100s matched 'Address "
"%.100s' at line %d", ci->address, arg, line);
break;
case 0:
case -1:
result = 0;
break;
case -2:
return -1;
}
} else if (strcasecmp(attrib, "localaddress") == 0){
if (ci == NULL || ci->laddress == NULL) {
result = 0;
continue;
}
switch (addr_match_list(ci->laddress, arg)) {
case 1:
debug("connection from %.100s matched "
"'LocalAddress %.100s' at line %d",
ci->laddress, arg, line);
break;
case 0:
case -1:
result = 0;
break;
case -2:
return -1;
}
} else if (strcasecmp(attrib, "localport") == 0) {
if ((port = a2port(arg)) == -1) {
error("Invalid LocalPort '%s' on Match line",
arg);
return -1;
}
if (ci == NULL || ci->lport == 0) {
result = 0;
continue;
}
/* TODO support port lists */
if (port == ci->lport)
debug("connection from %.100s matched "
"'LocalPort %d' at line %d",
ci->laddress, port, line);
else
result = 0;
} else if (strcasecmp(attrib, "rdomain") == 0) {
if (ci == NULL || ci->rdomain == NULL) {
result = 0;
continue;
}
if (match_pattern_list(ci->rdomain, arg, 0) != 1)
result = 0;
else
debug("user %.100s matched 'RDomain %.100s' at "
"line %d", ci->rdomain, arg, line);
} else {
error("Unsupported Match attribute %s", attrib);
return -1;
}
}
if (attributes == 0) {
error("One or more attributes required for Match");
return -1;
}
if (ci != NULL)
debug3("match %sfound", result ? "" : "not ");
*condition = cp;
return result;
}
#define WHITESPACE " \t\r\n"
/* Multistate option parsing */
struct multistate {
char *key;
int value;
};
static const struct multistate multistate_addressfamily[] = {
{ "inet", AF_INET },
{ "inet6", AF_INET6 },
{ "any", AF_UNSPEC },
{ NULL, -1 }
};
static const struct multistate multistate_permitrootlogin[] = {
{ "without-password", PERMIT_NO_PASSWD },
{ "prohibit-password", PERMIT_NO_PASSWD },
{ "forced-commands-only", PERMIT_FORCED_ONLY },
{ "yes", PERMIT_YES },
{ "no", PERMIT_NO },
{ NULL, -1 }
};
static const struct multistate multistate_compression[] = {
{ "yes", COMP_DELAYED },
{ "delayed", COMP_DELAYED },
{ "no", COMP_NONE },
{ NULL, -1 }
};
static const struct multistate multistate_gatewayports[] = {
{ "clientspecified", 2 },
{ "yes", 1 },
{ "no", 0 },
{ NULL, -1 }
};
static const struct multistate multistate_tcpfwd[] = {
{ "yes", FORWARD_ALLOW },
{ "all", FORWARD_ALLOW },
{ "no", FORWARD_DENY },
{ "remote", FORWARD_REMOTE },
{ "local", FORWARD_LOCAL },
{ NULL, -1 }
};
int
process_server_config_line(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep,
struct connection_info *connectinfo)
1999-10-27 11:42:43 +08:00
{
char *cp, **charptr, *arg, *arg2, *p;
int cmdline = 0, *intptr, value, value2, n, port;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
ServerOpCodes opcode;
u_int i, flags = 0;
size_t len;
long long val64;
const struct multistate *multistate_ptr;
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
return 0;
for (len--; len > 0; len--) {
if (strchr(WHITESPACE "\f", line[len]) == NULL)
break;
line[len] = '\0';
}
cp = line;
if ((arg = strdelim(&cp)) == NULL)
return 0;
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!arg || !*arg || *arg == '#')
return 0;
intptr = NULL;
charptr = NULL;
opcode = parse_token(arg, filename, linenum, &flags);
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
activep = &cmdline;
}
if (*activep && opcode != sMatch)
debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
if (connectinfo == NULL) {
fatal("%s line %d: Directive '%s' is not allowed "
"within a Match block", filename, linenum, arg);
} else { /* this is a directive we have already processed */
while (arg)
arg = strdelim(&cp);
return 0;
}
}
switch (opcode) {
/* Portable-specific options */
case sUsePAM:
intptr = &options->use_pam;
goto parse_flag;
/* Standard Options */
case sBadOption:
return -1;
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
return 0;
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.",
filename, linenum);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.",
filename, linenum);
options->ports[options->num_ports++] = a2port(arg);
if (options->ports[options->num_ports-1] <= 0)
fatal("%s line %d: Badly formatted port number.",
filename, linenum);
break;
case sLoginGraceTime:
intptr = &options->login_grace_time;
parse_time:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
filename, linenum);
if ((value = convtime(arg)) == -1)
fatal("%s line %d: invalid time value.",
filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sListenAddress:
arg = strdelim(&cp);
if (arg == NULL || *arg == '\0')
fatal("%s line %d: missing address",
filename, linenum);
/* check for bare IPv6 address: no "[]" and 2 or more ":" */
if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
&& strchr(p+1, ':') != NULL) {
port = 0;
p = arg;
} else {
p = hpdelim(&arg);
if (p == NULL)
fatal("%s line %d: bad address:port usage",
filename, linenum);
p = cleanhostname(p);
if (arg == NULL)
port = 0;
else if ((port = a2port(arg)) <= 0)
fatal("%s line %d: bad port number",
filename, linenum);
}
/* Optional routing table */
arg2 = NULL;
if ((arg = strdelim(&cp)) != NULL) {
if (strcmp(arg, "rdomain") != 0 ||
(arg2 = strdelim(&cp)) == NULL)
fatal("%s line %d: bad ListenAddress syntax",
filename, linenum);
if (!valid_rdomain(arg2))
fatal("%s line %d: bad routing domain",
filename, linenum);
}
queue_listen_addr(options, p, arg2, port);
break;
case sAddressFamily:
intptr = &options->address_family;
multistate_ptr = multistate_addressfamily;
parse_multistate:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing argument.",
filename, linenum);
value = -1;
for (i = 0; multistate_ptr[i].key != NULL; i++) {
if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
value = multistate_ptr[i].value;
break;
}
}
if (value == -1)
fatal("%s line %d: unsupported option \"%s\".",
filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sHostKeyFile:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep)
servconf_add_hostkey(filename, linenum, options, arg);
break;
case sHostKeyAgent:
charptr = &options->host_key_agent;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing socket name.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ?
xstrdup(arg) : derelativise_path(arg);
break;
case sHostCertificate:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep)
servconf_add_hostcert(filename, linenum, options, arg);
break;
case sPidFile:
charptr = &options->pid_file;
parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep && *charptr == NULL) {
*charptr = derelativise_path(arg);
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
multistate_ptr = multistate_permitrootlogin;
goto parse_multistate;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing yes/no argument.",
filename, linenum);
value = 0; /* silence compiler */
if (strcmp(arg, "yes") == 0)
value = 1;
else if (strcmp(arg, "no") == 0)
value = 0;
else
fatal("%s line %d: Bad yes/no argument: %s",
filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_flag;
case sHostbasedAuthentication:
intptr = &options->hostbased_authentication;
goto parse_flag;
case sHostbasedUsesNameFromPacketOnly:
intptr = &options->hostbased_uses_name_from_packet_only;
goto parse_flag;
case sHostbasedAcceptedKeyTypes:
charptr = &options->hostbased_key_types;
parse_keytypes:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (*arg != '-' &&
!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sHostKeyAlgorithms:
charptr = &options->hostkeyalgorithms;
goto parse_keytypes;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
case sPubkeyAcceptedKeyTypes:
charptr = &options->pubkey_key_types;
goto parse_keytypes;
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
case sKerberosGetAFSToken:
intptr = &options->kerberos_get_afs_token;
goto parse_flag;
case sGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
case sGssCleanupCreds:
intptr = &options->gss_cleanup_creds;
goto parse_flag;
case sGssStrictAcceptor:
intptr = &options->gss_strict_acceptor;
goto parse_flag;
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
case sChallengeResponseAuthentication:
intptr = &options->challenge_response_authentication;
goto parse_flag;
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sPrintLastLog:
intptr = &options->print_lastlog;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
parse_int:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing integer value.",
filename, linenum);
value = atoi(arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
1999-10-27 11:42:43 +08:00
case sX11UseLocalhost:
intptr = &options->x11_use_localhost;
goto parse_flag;
case sXAuthLocation:
charptr = &options->xauth_location;
goto parse_filename;
case sPermitTTY:
intptr = &options->permit_tty;
goto parse_flag;
case sPermitUserRC:
intptr = &options->permit_user_rc;
goto parse_flag;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sTCPKeepAlive:
intptr = &options->tcp_keep_alive;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sPermitUserEnvironment:
intptr = &options->permit_user_env;
goto parse_flag;
case sCompression:
intptr = &options->compression;
multistate_ptr = multistate_compression;
goto parse_multistate;
case sRekeyLimit:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
if (strcmp(arg, "default") == 0) {
val64 = 0;
} else {
if (scan_scaled(arg, &val64) == -1)
fatal("%.200s line %d: Bad number '%s': %s",
filename, linenum, arg, strerror(errno));
if (val64 != 0 && val64 < 16)
fatal("%.200s line %d: RekeyLimit too small",
filename, linenum);
}
if (*activep && options->rekey_limit == -1)
options->rekey_limit = val64;
if (cp != NULL) { /* optional rekey interval present */
if (strcmp(cp, "none") == 0) {
(void)strdelim(&cp); /* discard */
break;
}
intptr = &options->rekey_interval;
goto parse_time;
}
break;
case sGatewayPorts:
intptr = &options->fwd_opts.gateway_ports;
multistate_ptr = multistate_gatewayports;
goto parse_multistate;
case sUseDNS:
intptr = &options->use_dns;
goto parse_flag;
case sLogFacility:
log_facility_ptr = &options->log_facility;
arg = strdelim(&cp);
value = log_facility_number(arg);
if (value == SYSLOG_FACILITY_NOT_SET)
fatal("%.200s line %d: unsupported log facility '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*log_facility_ptr == -1)
*log_facility_ptr = (SyslogFacility) value;
break;
case sLogLevel:
log_level_ptr = &options->log_level;
arg = strdelim(&cp);
value = log_level_number(arg);
if (value == SYSLOG_LEVEL_NOT_SET)
fatal("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *log_level_ptr == -1)
*log_level_ptr = (LogLevel) value;
break;
case sAllowTcpForwarding:
intptr = &options->allow_tcp_forwarding;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowStreamLocalForwarding:
intptr = &options->allow_streamlocal_forwarding;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowAgentForwarding:
intptr = &options->allow_agent_forwarding;
goto parse_flag;
case sDisableForwarding:
intptr = &options->disable_forwarding;
goto parse_flag;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (match_user(NULL, NULL, NULL, arg) == -1)
fatal("%s line %d: invalid AllowUsers pattern: "
"\"%.100s\"", filename, linenum, arg);
if (!*activep)
continue;
array_append(filename, linenum, "AllowUsers",
&options->allow_users, &options->num_allow_users,
arg);
}
break;
case sDenyUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (match_user(NULL, NULL, NULL, arg) == -1)
fatal("%s line %d: invalid DenyUsers pattern: "
"\"%.100s\"", filename, linenum, arg);
if (!*activep)
continue;
array_append(filename, linenum, "DenyUsers",
&options->deny_users, &options->num_deny_users,
arg);
}
break;
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (!*activep)
continue;
array_append(filename, linenum, "AllowGroups",
&options->allow_groups, &options->num_allow_groups,
arg);
}
break;
case sDenyGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (!*activep)
continue;
array_append(filename, linenum, "DenyGroups",
&options->deny_groups, &options->num_deny_groups,
arg);
}
break;
case sCiphers:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case sMacs:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->macs == NULL)
options->macs = xstrdup(arg);
break;
case sKexAlgorithms:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (*arg != '-' &&
!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
case sSubsystem:
if (options->num_subsystems >= MAX_SUBSYSTEMS) {
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
if (!*activep) {
arg = strdelim(&cp);
break;
}
for (i = 0; i < options->num_subsystems; i++)
if (strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
filename, linenum, arg);
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
options->subsystem_command[options->num_subsystems] = xstrdup(arg);
/* Collect arguments (separate to executable) */
p = xstrdup(arg);
len = strlen(p) + 1;
while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
len += 1 + strlen(arg);
p = xreallocarray(p, 1, len);
strlcat(p, " ", len);
strlcat(p, arg, len);
}
options->subsystem_args[options->num_subsystems] = p;
options->num_subsystems++;
break;
case sMaxStartups:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing MaxStartups spec.",
filename, linenum);
if ((n = sscanf(arg, "%d:%d:%d",
&options->max_startups_begin,
&options->max_startups_rate,
&options->max_startups)) == 3) {
if (options->max_startups_begin >
options->max_startups ||
options->max_startups_rate > 100 ||
options->max_startups_rate < 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
} else if (n != 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
else
options->max_startups = options->max_startups_begin;
break;
case sMaxAuthTries:
intptr = &options->max_authtries;
goto parse_int;
case sMaxSessions:
intptr = &options->max_sessions;
goto parse_int;
case sBanner:
charptr = &options->banner;
goto parse_filename;
/*
* These options can contain %X options expanded at
* connect time, so that you can specify paths like:
*
* AuthorizedKeysFile /etc/ssh_keys/%u
*/
case sAuthorizedKeysFile:
if (*activep && options->num_authkeys_files == 0) {
while ((arg = strdelim(&cp)) && *arg != '\0') {
arg = tilde_expand_filename(arg, getuid());
array_append(filename, linenum,
"AuthorizedKeysFile",
&options->authorized_keys_files,
&options->num_authkeys_files, arg);
free(arg);
}
}
return 0;
case sAuthorizedPrincipalsFile:
charptr = &options->authorized_principals_file;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep && *charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sClientAliveInterval:
intptr = &options->client_alive_interval;
goto parse_time;
case sClientAliveCountMax:
intptr = &options->client_alive_count_max;
goto parse_int;
case sAcceptEnv:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (strchr(arg, '=') != NULL)
fatal("%s line %d: Invalid environment name.",
filename, linenum);
if (!*activep)
continue;
array_append(filename, linenum, "AcceptEnv",
&options->accept_env, &options->num_accept_env,
arg);
}
break;
case sPermitTunnel:
intptr = &options->permit_tun;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing yes/point-to-point/"
"ethernet/no argument.", filename, linenum);
value = -1;
for (i = 0; tunmode_desc[i].val != -1; i++)
if (strcmp(tunmode_desc[i].text, arg) == 0) {
value = tunmode_desc[i].val;
break;
}
if (value == -1)
fatal("%s line %d: Bad yes/point-to-point/ethernet/"
"no argument: %s", filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sMatch:
if (cmdline)
fatal("Match directive not supported as a command-line "
"option");
value = match_cfg_line(&cp, linenum, connectinfo);
if (value < 0)
fatal("%s line %d: Bad Match condition", filename,
linenum);
*activep = value;
break;
case sPermitOpen:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing PermitOpen specification",
filename, linenum);
value = options->num_permitted_opens; /* modified later */
if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
if (*activep && value == 0) {
options->num_permitted_opens = 1;
options->permitted_opens = xcalloc(1,
sizeof(*options->permitted_opens));
options->permitted_opens[0] = xstrdup(arg);
}
break;
}
for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
arg2 = xstrdup(arg);
p = hpdelim(&arg);
if (p == NULL)
fatal("%s line %d: missing host in PermitOpen",
filename, linenum);
p = cleanhostname(p);
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
fatal("%s line %d: bad port number in "
"PermitOpen", filename, linenum);
if (*activep && value == 0) {
array_append(filename, linenum,
"PermitOpen",
&options->permitted_opens,
&options->num_permitted_opens, arg2);
}
free(arg2);
}
break;
case sForceCommand:
if (cp == NULL || *cp == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep && options->adm_forced_command == NULL)
options->adm_forced_command = xstrdup(cp + len);
return 0;
case sChrootDirectory:
charptr = &options->chroot_directory;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sTrustedUserCAKeys:
charptr = &options->trusted_user_ca_keys;
goto parse_filename;
case sRevokedKeys:
charptr = &options->revoked_keys_file;
goto parse_filename;
case sIPQoS:
arg = strdelim(&cp);
if ((value = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
arg = strdelim(&cp);
if (arg == NULL)
value2 = value;
else if ((value2 = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
if (*activep) {
options->ip_qos_interactive = value;
options->ip_qos_bulk = value2;
}
break;
case sVersionAddendum:
if (cp == NULL || *cp == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep && options->version_addendum == NULL) {
if (strcasecmp(cp + len, "none") == 0)
options->version_addendum = xstrdup("");
else if (strchr(cp + len, '\r') != NULL)
fatal("%.200s line %d: Invalid argument",
filename, linenum);
else
options->version_addendum = xstrdup(cp + len);
}
return 0;
case sAuthorizedKeysCommand:
if (cp == NULL)
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep && options->authorized_keys_command == NULL) {
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
fatal("%.200s line %d: AuthorizedKeysCommand "
"must be an absolute path",
filename, linenum);
options->authorized_keys_command = xstrdup(cp + len);
}
return 0;
case sAuthorizedKeysCommandUser:
charptr = &options->authorized_keys_command_user;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing AuthorizedKeysCommandUser "
"argument.", filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sAuthorizedPrincipalsCommand:
if (cp == NULL)
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep &&
options->authorized_principals_command == NULL) {
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
fatal("%.200s line %d: "
"AuthorizedPrincipalsCommand must be "
"an absolute path", filename, linenum);
options->authorized_principals_command =
xstrdup(cp + len);
}
return 0;
case sAuthorizedPrincipalsCommandUser:
charptr = &options->authorized_principals_command_user;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing "
"AuthorizedPrincipalsCommandUser argument.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sAuthenticationMethods:
if (options->num_auth_methods == 0) {
value = 0; /* seen "any" pseudo-method */
value2 = 0; /* sucessfully parsed any method */
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (strcmp(arg, "any") == 0) {
if (options->num_auth_methods > 0) {
fatal("%s line %d: \"any\" "
"must appear alone in "
"AuthenticationMethods",
filename, linenum);
}
value = 1;
} else if (value) {
fatal("%s line %d: \"any\" must appear "
"alone in AuthenticationMethods",
filename, linenum);
} else if (auth2_methods_valid(arg, 0) != 0) {
fatal("%s line %d: invalid "
"authentication method list.",
filename, linenum);
}
value2 = 1;
if (!*activep)
continue;
array_append(filename, linenum,
"AuthenticationMethods",
&options->auth_methods,
&options->num_auth_methods, arg);
}
if (value2 == 0) {
fatal("%s line %d: no AuthenticationMethods "
"specified", filename, linenum);
}
}
return 0;
case sStreamLocalBindMask:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing StreamLocalBindMask "
"argument.", filename, linenum);
/* Parse mode in octal format */
value = strtol(arg, &p, 8);
if (arg == p || value < 0 || value > 0777)
fatal("%s line %d: Bad mask.", filename, linenum);
if (*activep)
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
case sStreamLocalBindUnlink:
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
case sFingerprintHash:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if ((value = ssh_digest_alg_by_name(arg)) == -1)
fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
filename, linenum, arg);
if (*activep)
options->fingerprint_hash = value;
break;
case sExposeAuthInfo:
intptr = &options->expose_userauth_info;
goto parse_flag;
case sRDomain:
charptr = &options->routing_domain;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
!valid_rdomain(arg))
fatal("%s line %d: bad routing domain",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
case sDeprecated:
case sIgnore:
case sUnsupported:
do_log2(opcode == sIgnore ?
SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
"%s line %d: %s option %s", filename, linenum,
opcode == sUnsupported ? "Unsupported" : "Deprecated", arg);
while (arg)
arg = strdelim(&cp);
break;
default:
fatal("%s line %d: Missing handler for opcode %s (%d)",
filename, linenum, arg, opcode);
}
if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
fatal("%s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
return 0;
}
/* Reads the server configuration file. */
void
load_server_config(const char *filename, Buffer *conf)
{
char line[4096], *cp;
FILE *f;
int lineno = 0;
debug2("%s: filename %s", __func__, filename);
if ((f = fopen(filename, "r")) == NULL) {
perror(filename);
exit(1);
}
buffer_clear(conf);
while (fgets(line, sizeof(line), f)) {
lineno++;
if (strlen(line) == sizeof(line) - 1)
fatal("%s line %d too long", filename, lineno);
/*
* Trim out comments and strip whitespace
* NB - preserve newlines, they are needed to reproduce
* line numbers later for error messages
*/
if ((cp = strchr(line, '#')) != NULL)
memcpy(cp, "\n", 2);
cp = line + strspn(line, " \t\r");
buffer_append(conf, cp, strlen(cp));
1999-10-27 11:42:43 +08:00
}
buffer_append(conf, "\0", 1);
fclose(f);
debug2("%s: done config len = %d", __func__, buffer_len(conf));
}
void
parse_server_match_config(ServerOptions *options,
struct connection_info *connectinfo)
{
ServerOptions mo;
initialize_server_options(&mo);
parse_server_config(&mo, "reprocess config", &cfg, connectinfo);
copy_set_server_options(options, &mo, 0);
}
int parse_server_match_testspec(struct connection_info *ci, char *spec)
{
char *p;
while ((p = strsep(&spec, ",")) && *p != '\0') {
if (strncmp(p, "addr=", 5) == 0) {
ci->address = xstrdup(p + 5);
} else if (strncmp(p, "host=", 5) == 0) {
ci->host = xstrdup(p + 5);
} else if (strncmp(p, "user=", 5) == 0) {
ci->user = xstrdup(p + 5);
} else if (strncmp(p, "laddr=", 6) == 0) {
ci->laddress = xstrdup(p + 6);
} else if (strncmp(p, "rdomain=", 8) == 0) {
ci->rdomain = xstrdup(p + 8);
} else if (strncmp(p, "lport=", 6) == 0) {
ci->lport = a2port(p + 6);
if (ci->lport == -1) {
fprintf(stderr, "Invalid port '%s' in test mode"
" specification %s\n", p+6, p);
return -1;
}
} else {
fprintf(stderr, "Invalid test mode specification %s\n",
p);
return -1;
}
}
return 0;
}
/*
* returns 1 for a complete spec, 0 for partial spec and -1 for an
* empty spec.
*/
int server_match_spec_complete(struct connection_info *ci)
{
if (ci->user && ci->host && ci->address)
return 1; /* complete */
if (!ci->user && !ci->host && !ci->address)
return -1; /* empty */
return 0; /* partial */
}
/*
* Copy any supported values that are set.
*
* If the preauth flag is set, we do not bother copying the string or
* array values that are not used pre-authentication, because any that we
* do use must be explictly sent in mm_getpwnamallow().
*/
void
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
{
#define M_CP_INTOPT(n) do {\
if (src->n != -1) \
dst->n = src->n; \
} while (0)
M_CP_INTOPT(password_authentication);
M_CP_INTOPT(gss_authentication);
M_CP_INTOPT(pubkey_authentication);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
M_CP_INTOPT(allow_tcp_forwarding);
M_CP_INTOPT(allow_streamlocal_forwarding);
M_CP_INTOPT(allow_agent_forwarding);
M_CP_INTOPT(disable_forwarding);
M_CP_INTOPT(expose_userauth_info);
M_CP_INTOPT(permit_tun);
M_CP_INTOPT(fwd_opts.gateway_ports);
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding);
M_CP_INTOPT(x11_use_localhost);
M_CP_INTOPT(permit_tty);
M_CP_INTOPT(permit_user_rc);
M_CP_INTOPT(max_sessions);
M_CP_INTOPT(max_authtries);
M_CP_INTOPT(client_alive_count_max);
M_CP_INTOPT(client_alive_interval);
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
M_CP_INTOPT(log_level);
/*
* The bind_mask is a mode_t that may be unsigned, so we can't use
* M_CP_INTOPT - it does a signed comparison that causes compiler
* warnings.
*/
if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) {
dst->fwd_opts.streamlocal_bind_mask =
src->fwd_opts.streamlocal_bind_mask;
}
/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
#define M_CP_STROPT(n) do {\
if (src->n != NULL && dst->n != src->n) { \
free(dst->n); \
dst->n = src->n; \
} \
} while(0)
#define M_CP_STRARRAYOPT(s, num_s) do {\
u_int i; \
if (src->num_s != 0) { \
for (i = 0; i < dst->num_s; i++) \
free(dst->s[i]); \
free(dst->s); \
dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \
for (i = 0; i < src->num_s; i++) \
dst->s[i] = xstrdup(src->s[i]); \
dst->num_s = src->num_s; \
} \
} while(0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
/* Arguments that accept '+...' need to be expanded */
assemble_algorithms(dst);
/*
* The only things that should be below this point are string options
* which are only used after authentication.
*/
if (preauth)
return;
/* These options may be "none" to clear a global setting */
M_CP_STROPT(adm_forced_command);
if (option_clear_or_none(dst->adm_forced_command)) {
free(dst->adm_forced_command);
dst->adm_forced_command = NULL;
}
M_CP_STROPT(chroot_directory);
if (option_clear_or_none(dst->chroot_directory)) {
free(dst->chroot_directory);
dst->chroot_directory = NULL;
}
}
#undef M_CP_INTOPT
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
void
parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
struct connection_info *connectinfo)
{
int active, linenum, bad_options = 0;
char *cp, *obuf, *cbuf;
debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
active = connectinfo ? 0 : 1;
linenum = 1;
while ((cp = strsep(&cbuf, "\n")) != NULL) {
if (process_server_config_line(options, cp, filename,
linenum++, &active, connectinfo) != 0)
bad_options++;
}
free(obuf);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);
process_queued_listen_addrs(options);
1999-10-27 11:42:43 +08:00
}
static const char *
fmt_multistate_int(int val, const struct multistate *m)
{
u_int i;
for (i = 0; m[i].key != NULL; i++) {
if (m[i].value == val)
return m[i].key;
}
return "UNKNOWN";
}
static const char *
fmt_intarg(ServerOpCodes code, int val)
{
if (val == -1)
return "unset";
switch (code) {
case sAddressFamily:
return fmt_multistate_int(val, multistate_addressfamily);
case sPermitRootLogin:
return fmt_multistate_int(val, multistate_permitrootlogin);
case sGatewayPorts:
return fmt_multistate_int(val, multistate_gatewayports);
case sCompression:
return fmt_multistate_int(val, multistate_compression);
case sAllowTcpForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sFingerprintHash:
return ssh_digest_alg_name(val);
default:
switch (val) {
case 0:
return "no";
case 1:
return "yes";
default:
return "UNKNOWN";
}
}
}
static const char *
lookup_opcode_name(ServerOpCodes code)
{
u_int i;
for (i = 0; keywords[i].name != NULL; i++)
if (keywords[i].opcode == code)
return(keywords[i].name);
return "UNKNOWN";
}
static void
dump_cfg_int(ServerOpCodes code, int val)
{
printf("%s %d\n", lookup_opcode_name(code), val);
}
static void
dump_cfg_oct(ServerOpCodes code, int val)
{
printf("%s 0%o\n", lookup_opcode_name(code), val);
}
static void
dump_cfg_fmtint(ServerOpCodes code, int val)
{
printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
}
static void
dump_cfg_string(ServerOpCodes code, const char *val)
{
printf("%s %s\n", lookup_opcode_name(code),
val == NULL ? "none" : val);
}
static void
dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
{
u_int i;
for (i = 0; i < count; i++)
printf("%s %s\n", lookup_opcode_name(code), vals[i]);
}
static void
dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
{
u_int i;
if (count <= 0 && code != sAuthenticationMethods)
return;
printf("%s", lookup_opcode_name(code));
for (i = 0; i < count; i++)
printf(" %s", vals[i]);
if (code == sAuthenticationMethods && count == 0)
printf(" any");
printf("\n");
}
static char *
format_listen_addrs(struct listenaddr *la)
{
int r;
struct addrinfo *ai;
char addr[NI_MAXHOST], port[NI_MAXSERV];
char *laddr1 = xstrdup(""), *laddr2 = NULL;
/*
* ListenAddress must be after Port. add_one_listen_addr pushes
* addresses onto a stack, so to maintain ordering we need to
* print these in reverse order.
*/
for (ai = la->addrs; ai; ai = ai->ai_next) {
if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
sizeof(addr), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
error("getnameinfo: %.100s", ssh_gai_strerror(r));
continue;
}
laddr2 = laddr1;
if (ai->ai_family == AF_INET6) {
xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
addr, port,
la->rdomain == NULL ? "" : " rdomain ",
la->rdomain == NULL ? "" : la->rdomain,
laddr2);
} else {
xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
addr, port,
la->rdomain == NULL ? "" : " rdomain ",
la->rdomain == NULL ? "" : la->rdomain,
laddr2);
}
free(laddr2);
}
return laddr1;
}
void
dump_config(ServerOptions *o)
{
char *s;
u_int i;
/* these are usually at the top of the config */
for (i = 0; i < o->num_ports; i++)
printf("port %d\n", o->ports[i]);
dump_cfg_fmtint(sAddressFamily, o->address_family);
for (i = 0; i < o->num_listen_addrs; i++) {
s = format_listen_addrs(&o->listen_addrs[i]);
printf("%s", s);
free(s);
}
/* integer arguments */
#ifdef USE_PAM
dump_cfg_fmtint(sUsePAM, o->use_pam);
#endif
dump_cfg_int(sLoginGraceTime, o->login_grace_time);
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
dump_cfg_int(sMaxAuthTries, o->max_authtries);
dump_cfg_int(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
/* formatted integer arguments */
dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
o->hostbased_uses_name_from_packet_only);
dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
#ifdef KRB5
dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
# ifdef USE_AFS
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
# endif
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
o->kbd_interactive_authentication);
dump_cfg_fmtint(sChallengeResponseAuthentication,
o->challenge_response_authentication);
dump_cfg_fmtint(sPrintMotd, o->print_motd);
#ifndef DISABLE_LASTLOG
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
#endif
dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
dump_cfg_fmtint(sPermitTTY, o->permit_tty);
dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc);
dump_cfg_fmtint(sStrictModes, o->strict_modes);
dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT);
dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
dump_cfg_string(sBanner, o->banner);
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
dump_cfg_string(sAuthorizedPrincipalsFile,
o->authorized_principals_file);
dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
? "none" : o->version_addendum);
dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command);
dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user);
dump_cfg_string(sHostKeyAgent, o->host_key_agent);
dump_cfg_string(sKexAlgorithms,
2014-10-13 08:38:35 +08:00
o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX);
dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ?
o->hostbased_key_types : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ?
o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sRDomain, o->routing_domain);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
/* string array arguments */
dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
o->authorized_keys_files);
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
o->host_key_files);
dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
o->host_cert_files);
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
dump_cfg_strarray_oneline(sAuthenticationMethods,
o->num_auth_methods, o->auth_methods);
/* other arguments */
for (i = 0; i < o->num_subsystems; i++)
printf("subsystem %s %s\n", o->subsystem_name[i],
o->subsystem_args[i]);
printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
o->max_startups_rate, o->max_startups);
for (i = 0; tunmode_desc[i].val != -1; i++)
if (tunmode_desc[i].val == o->permit_tun) {
s = tunmode_desc[i].text;
break;
}
dump_cfg_string(sPermitTunnel, s);
printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
printf("%s\n", iptos2str(o->ip_qos_bulk));
printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
o->rekey_interval);
printf("permitopen");
if (o->num_permitted_opens == 0)
printf(" any");
else {
for (i = 0; i < o->num_permitted_opens; i++)
printf(" %s", o->permitted_opens[i]);
}
printf("\n");
}