198 Commits

Author SHA1 Message Date
bd62ad15e5 Trigger installation of libssh
Change-Id: I41e499d040c5102234ad78370597e76a7de7f4b8
2017-10-08 17:22:20 +02:00
c45c9fc420 Config files installation works now
Change-Id: I2f0b23d8bce56cf00eeb5a22631145bd29f8a271
2017-10-08 17:18:40 +02:00
James T. Sprinkle
61020f23a6 Moved some Makefiles around to allow for install of configuration files. 2017-10-04 17:41:00 -07:00
James T. Sprinkle
6d74a5ac99 Added /etc/ssh to NetBSD.dist.base to create directory 2017-10-03 09:55:18 -07:00
James T. Sprinkle
9e1f6eaec7 New files for previous update. 2017-10-01 16:50:39 -07:00
James T. Sprinkle
b54c312497 Buildable openssh.
2 known bugs:
 . Build doesn't copy libssh* to the destination directory.
   + workaround is to copy them from the lib directory to destination and recreate links
 . ssh_config and sshd_config don't install
   + workaround is to copy them manually

Note the software doesn't build to completion until you do the workarounds.
Still trying to sort this out, but wanted to get these changes up for more
visibility and collaboration.
2017-10-01 16:42:37 -07:00
James T. Sprinkle
58a339025d Added BBB_MEM_FULL switch to allow for building with 512M memory on BBB 2017-09-28 06:21:08 -07:00
James T. Sprinkle
a69f786a89 Modified Makefile to remove .if specific to Minix
Added netbsd repo version of src/crypto/external/bsd/openssh initial baseline
2017-09-26 18:13:36 -07:00
Jean-Baptiste Boric
39d31d9fab ARM: Remove dependency on mtools
Instead of formatting the image, and then using the mtools to copy on it
the boot partition files, we use makefs to directly generate the
partition.

Change-Id: I468e3100842177f3f55edbfdb910941bafa576ba
2017-07-12 08:20:16 +02:00
rlfnb
b67d2ae9e2 Fixed broken multiboot struct
Change-Id: Ib59fb04a45c4417588bf204a5a6e6306f5097e22
2017-07-12 07:40:10 +02:00
rlfnb
d4dd6511b9 replace tickdelay with micro_delay to be quantum-agnostic
Change-Id: Ie449d797389a178372035d797c84b02d636788cd
2017-06-01 19:48:56 +02:00
David van Moolenbroek
3e2c6c9674 isofs: support directories with many entries
In particular, remove the hardcoded limit of 4096 entries in a single
directory, as there are (at least) real DVDs out there with more
entries than that.  The implementation of this change requires a
second pass on large directories; performance optimizations are left
to future work.

Change-Id: Ia865ac95797fa2dd36b086779c3f1fef6b2f6a6f
2017-05-17 23:25:11 +00:00
David van Moolenbroek
502e7ff953 at_wini: bump hardcoded ATAPI limit to DVD size
at_wini was previously hardcoded to present ATAPI devices as having a
size of 800 MiB, which was enough for CDs but not for DVDs.  This
patch increases the device size to 8500 MiB, which should be large
enough to cover all DVDs.

Change-Id: I7d3192e4ecd0708a655663c1007ff517ed969580
2017-05-17 23:16:52 +00:00
Antoine Leca
d5e4fc0151 Fix Makefile.boot small issue sync'ing with NetBSD
Change-Id: I4f8cbfb9d4b6be8b31ce705cbecc4b12b7e1fe45
2017-05-08 12:15:09 +00:00
David van Moolenbroek
9f81acbc21 Fix lua
As reported by Jean-Baptiste Boric, lua would refuse to start,
throwing an error about incompatibility of numeric types.

This resolves #160.

Change-Id: I5cd6c3b2a35c7023946e4d14d4feedaaecb956fb
2017-05-08 11:53:38 +00:00
rlfnb
9624407e7a header cleanup
Change-Id: I4e169911591c56e91c301c5cb0bb3ea2d8140cf2
2017-05-07 14:02:00 +02:00
Jean-Baptiste Boric
c1d4abeb0c Fix pkgin_cd.sh
Change-Id: I513c16b0691897f3c665532d50ed398967f3e4d0
2017-05-07 00:54:46 +02:00
Jean-Baptiste Boric
66e071a40c Add releasetools/pkgsrc_cdimage.sh
This script uses the image generation framework to create a pkgsrc CD
image, useful for MINIX installations without Internet connectivity.

Change-Id: Ife037f6b6958e38986afad0632f37999ecbb2b55
2017-05-07 00:54:46 +02:00
Jean-Baptiste Boric
0884854a38 Rework package bundling mechanism
Setting PACKAGE_DIR without PACKAGES will default to bundling all
packages in PACKAGE_DIR. PKG_INFO is also mandatory now.

Change-Id: Iaf02221ec91e9c54dc8caec6e9a01bccfc65cc31
2017-05-07 00:54:45 +02:00
Ben Mezger
1915559884 Removed unused variable and cleaned whitespaces
Change-Id: Iaaf6b6f5f49f2d2599a3422250ad7e6e41838b82
2017-05-07 00:54:44 +02:00
Ben Mezger
afc65e92aa Removed unused variables and cleaned whitespaces.
Change-Id: Ib96d1c5bf7a1c65a99d77726fe54ccf37399f9eb
2017-05-07 00:54:43 +02:00
Ben Mezger
9f7f0ad073 Removed unused variables and cleaned whitespaces.
Change-Id: Ie5c1ad84ad162ab18443dd228686aba544ecb9ef
2017-05-07 00:54:43 +02:00
Ben Mezger
81ae2bc455 Prevent arg from being used any further
Patch edited by David van Moolenbroek.

Change-Id: Ie25faffea359e735145dbb4ae2bd2d213488952b
2017-05-07 00:54:19 +02:00
David van Moolenbroek
62cf0e1226 distrib: fix debug builds
Reported by Jean-Baptiste Boric.

Change-Id: I1e9b156326385aa188c824557b6716c059e39fce
2017-05-06 14:43:03 +02:00
David van Moolenbroek
79a488aa87 Network stack feedback-based fixes
Thanks to Lionel Sambuc!

Change-Id: Iae6b2caf58e2b58093e60c5004cfa477e43da154
2017-04-30 17:37:10 +02:00
David van Moolenbroek
3ba6090f82 tests: add advanced TCP/IP tests (test91-94)
Change-Id: I052102f6122f82b3307595990bf91f64e97a45a8
2017-04-30 13:16:25 +00:00
David van Moolenbroek
1dee92ebe9 Import NetBSD networking rc scripts
IMPORTANT: this change has a docs/UPDATING entry!

Change-Id: I6f1e575166f5b47530a004c12aea9b45b571e13d
2017-04-30 13:16:22 +00:00
David van Moolenbroek
9a8b4f5601 netconf(8): rewrite
When possible, network drivers are now started automatically.  That
means that netconf(8)'s network driver selection has become obsolete.
This patch changes netconf(8) to allow the user to specify a network
configuration (currently one of DHCP IPv4+IPv6, DHCP IPv4-only,
manual IPv4-only) for any hardware network interfaces that are
currently present.

Selection of network drivers that require manual configuration first
(mainly old ISA cards) is still supported, but now as a special case.

Change-Id: I6208fc75192eb7f0b061862aaf7507f71a620da4
2017-04-30 13:16:19 +00:00
David van Moolenbroek
60299d873c etc/rc: start lwip service
Change-Id: I10cfdcde490987b93c79532a2c53dda2307b83ce
2017-04-30 13:16:16 +00:00
David van Moolenbroek
e4dbab1e53 etc/rc: auto-start PnP ethernet drivers
Change-Id: I0f6c955511cbb04d47093de28109b5084609856a
2017-04-30 13:16:13 +00:00
David van Moolenbroek
ad920fc485 tests: adapt existing tests to new LWIP service
Change-Id: Id744e9d3fbe19733557011f8803593cf3768c35d
2017-04-30 13:16:10 +00:00
David van Moolenbroek
bb9622b5ed ping(8), traceroute(8): adapt to new LWIP service
Change-Id: I0aae7199dfd9075201975e133cdaeab6bc2bd24f
2017-04-30 13:16:06 +00:00
David van Moolenbroek
ef8d499e2d Add lwip: a new lwIP-based TCP/IP service
This commit adds a new TCP/IP service to MINIX 3.  As its core, the
service uses the lwIP TCP/IP stack for maintenance reasons.  The
service aims to be compatible with NetBSD userland, including its
low-level network management utilities.  It also aims to support
modern features such as IPv6.  In summary, the new LWIP service has
support for the following main features:

- TCP, UDP, RAW sockets with mostly standard BSD API semantics;
- IPv6 support: host mode (complete) and router mode (partial);
- most of the standard BSD API socket options (SO_);
- all of the standard BSD API message flags (MSG_);
- the most used protocol-specific socket and control options;
- a default loopback interface and the ability to create one more;
- configuration-free ethernet interfaces and driver tracking;
- queuing and multiple concurrent requests to each ethernet driver;
- standard ioctl(2)-based BSD interface management;
- radix tree backed, destination-based routing;
- routing sockets for standard BSD route reporting and management;
- multicast traffic and multicast group membership tracking;
- Berkeley Packet Filter (BPF) devices;
- standard and custom sysctl(7) nodes for many internals;
- a slab allocation based, hybrid static/dynamic memory pool model.

Many of its modules come with fairly elaborate comments that cover
many aspects of what is going on.  The service is primarily a socket
driver built on top of the libsockdriver library, but for BPF devices
it is at the same time also a character driver.

Change-Id: Ib0c02736234b21143915e5fcc0fda8fe408f046f
2017-04-30 13:16:03 +00:00
David van Moolenbroek
0f03189a6a RMIB: add indirection support for sparse subtrees
Normally, each RMIB subtree consists of an array of nodes, indexed
by node identifier.  In a sparsely filled subtree, most of the array
is empty and just wasting memory.  In that case, it may be beneficial
to have a level of indirection, with an intermediate array containing
pairs of node IDs and pointers to the actual nodes.  This patch adds
support for such indirection.

For the use cases that inspired this patch, net.inet and net.inet6,
the indirection shaves off a little under 16KB of memory from the
TCP/IP service.

Change-Id: Ic68ca3fee1a0f2032f77eef6df42728f9b9400e8
2017-04-30 13:16:00 +00:00
David van Moolenbroek
5edbea5063 libsys: allow for grant preallocation
Since the grant table is allocated dynamically, a system service always
runs the risk of running out of memory at run time when trying to
allocate a grant.  In order to allow services to mitigate that risk,
grants can now be preallocated, typically at system service startup,
using the new cpf_prealloc(3) libsys function.  The function takes a
'count' parameter that indicates the number of additional grants to
preallocate.  Thus, the function may be called from multiple submodules
within a service, each preallocating their own maximum of grants that
it may need at run time.

Change-Id: I6904726a722a8c27dfe2efa470e683718f310272
2017-04-30 13:15:57 +00:00
David van Moolenbroek
5d5fbe79c1 Import new lwIP version into liblwip
In order to match NetBSD-style imports of external code, the library
has been restructured.  The full lwIP source tree is imported, except
for a few .git* files in its root directory, into dist/.  The MINIX 3
Makefiles and other custom files are located in lib/.  Finally, since
we need to apply a number of small patches to lwIP, these patches are
stored in patches/, in addition to being applied to the lwIP tree.

The currently imported version of lwIP is taken from its master
branch sometime after the 2.0.1 release, specifically git-7ffe5bf.

Change-Id: Ie03c4fa36fa928870263c191205d6d93f652a3cc
2017-04-30 13:15:53 +00:00
David van Moolenbroek
47db417b1a lance: perform full reinitialization for restarts
When performing a restart (CSR0 STOP, STRT), the behavior regarding
the NIC's current RX/TX descriptor ring counters varies between cards:
older LANCE cards do not reset the counters; newer PCnet cards do
reset them; VirtualBox's emulation is once again broken in that it
claims to emulate newer cards but implements the older behavior.

Changing the card's receive mode requires such a restart, and now that
the system can actually change receive modes dynamically as part of
normal network operation, this results in the lance driver breaking
all the time on at least VirtualBox.

Instead of trying to figure out exactly what is going on with the
counters during a restart, we now simply perform a full-blown
reinitialization every time the NIC is restarted.  That leaves no
ambiguity regarding the counters, and appears to be what drivers on
other OSes do as well.  As a bonus, this approach actually saves code.

Change-Id: I60fad2df6de4616d5de2cec39c09b60c15d854fb
2017-04-30 13:15:50 +00:00
David van Moolenbroek
f7df02e747 libnetdriver: rewrite
This is a driver-breaking update to the netdriver library, which is
used by all network drivers.  The aim of this change is to make the
library more compatible with NetBSD, and in particular with various
features that are expected to be supported by the NetBSD userland.
The main changes made by this patch are the following:

- each network driver now has a NetBSD-style short device name;
- drivers are not expected to receive packets right after startup;
- extended support for receipt modes, including multicast lists;
- support for multiple parallel send, receive requests;
- embedding of I/O vectors in send and receive requests;
- support for capabilities, including checksum offloading;
- support for reporting link status updates to the TCP/IP stack;
- support for setting and retrieving media status;
- support for changing the hardware (MAC) address;
- support for NetBSD interface flags IFF_DEBUG, IFF_LINK[0-2];
- support for NetBSD error statistics;
- support for regular time-based ("tick") callbacks.

IMPORTANT: this patch applies a minimal update to the existing drivers
in order to make them work at all with the new netdriver library.  It
however does *not* change all drivers to make use of the new features.
In fact, strictly speaking, all drivers are now violating requirements
imposed by the new library in one way or another, most notably by
enabling packet receipt when starting the driver.  Changing all the
drivers to be compliant, and to support the newly added options, is
left to future patches.  The existing drivers should currently *not*
be taken as examples of how to implement a new network driver!

With that said, a few drivers have already been changed to make use of
some of the new features: fxp, e1000, rtl8139, and rtl8169 now report
link and media status, and the last three of those now support setting
the hardware MAC address on the fly.  In addition, dp8390 has been
changed to default to PCI autoconfiguration if no configuration is
specified through environment variables.

Change-Id: I4b3ea9c0b9bc25d5b0609c6ff256fb0db71cdc42
2017-04-30 13:15:28 +00:00
David van Moolenbroek
686761dbbc syslogd(8): drop some MINIX-specific changes
Change-Id: Ic286b89975eeea1abf0d5086ee13dfb9ab57d8ba
2017-03-21 22:00:37 +00:00
David van Moolenbroek
5bded7c030 ftpd(8): drop some MINIX-specific changes
Also put in a crude way to clean up zombies when ftpd(8) is running
in daemon mode, because we do not yet support SA_NOCLDWAIT.

Change-Id: I8a7db1d665c432d736db833b0022d0340764db1f
2017-03-21 22:00:34 +00:00
David van Moolenbroek
340f5e5660 Import NetBSD httpd(8)
Also known as bozohttpd(8).

Change-Id: I40e955b5654674f2c708b10e5e403ca9cbc92534
2017-03-21 22:00:31 +00:00
David van Moolenbroek
8f957290eb Import NetBSD rtadvd(8)
Change-Id: I22626843d85c78f0fadefd58d61d7a85d285b2b8
2017-03-21 22:00:28 +00:00
David van Moolenbroek
5de448e315 Import NetBSD ndp(8)
Like arp(8), this utility already uses the NetBSD 8 protocol for
talking to the operating system through routing sockets.

Like arp(8), this utility is not fully functional, due to limitations
of lwIP.  While ndp(8) should provide a proper (read-only) view of the
contents of the Neighbor Discovery table, any attempts to modify the
table will fail.  In addition, various other ndp(8) features are not
supported.  On MINIX 3, the prefix and default router lists are not
managed by the operating system however, but rather by dhcpcd(8);
therefore, an implementation of the features related to those lists
would not provide any actual functionality.

Change-Id: I479bfc8141ba69fe50c1b2f7091933267ce6fa3e
2017-03-21 22:00:25 +00:00
David van Moolenbroek
b636d99d91 Import NetBSD tcpdump(8)
For now, printing of Sun RPC requests is disabled because we do not
yet have the RPC header files.  This should affect basically noone,
as we do not have any RPC-based programs yet, for the same reason.

Change-Id: Ie7818faaaacdc104d8b2c37a68866b4ce18247d6
2017-03-21 22:00:21 +00:00
David van Moolenbroek
d56f51ea7d Import NetBSD libpcap
As part of this, we import bpf_filter.c from NetBSD.  Even though that
file is part of the NetBSD kernel, it is also used by userland (as is
clear here).  Our LWIP service has its own bpf_filter.c implementation
but that implementation has certain limits (e.g. on program size) that
are fine for a system service but should not apply to userland.

The libpcap code has a number of blocks guarded by __NetBSD__, but
none of those blocks apply to MINIX 3.  In particular, some of the
alignment logic used for NetBSD may in fact not work in our case.

Change-Id: Ib187e22d627c929e111d5d4a991c3bee3c0154cb
2017-03-21 22:00:18 +00:00
David van Moolenbroek
83ee113ee0 Import NetBSD dhclient(8), dhcpd(8), dhcrelay(8)
dhcrelay(8) and omshell(1) have not been tested.

Change-Id: I0cad89f65666af4e366a86e130ce8df0894c3bb4
2017-03-21 22:00:14 +00:00
David van Moolenbroek
00b67f09dd Import NetBSD named(8)
Also known as ISC bind.  This import adds utilities such as host(1),
dig(1), and nslookup(1), as well as many other tools and libraries.

Change-Id: I035ca46e64f1965d57019e773f4ff0ef035e4aa3
2017-03-21 22:00:06 +00:00
David van Moolenbroek
9f20bfa6c4 Import NetBSD dhcpcd(8)
The port could be improved by adding support for pselect(2).

Other than that, this port has a few MINIX-specific changes:

- we undefine IN_IFF_ flags to stop dhcpcd from thinking that we have
  operating system support for link-local IPv4 address management;
- we work around one crash bug that seems triggered by using dhcpcd
  on some but not all interfaces;
- we add "noalias" to the default dhcpcd.conf(5) configuration file.

Change-Id: I8a81c2c2af353c5ce08335673b1ab2d4b39178da
2017-03-21 21:59:13 +00:00
David van Moolenbroek
d642636d2d Import NetBSD resolvconf(8)
Also known as "openresolv".  Needed for dhcpcd(8).

Change-Id: Ibcb616837e9a5293377e451c6f6218a37260ed80
2017-03-09 23:40:18 +00:00
David van Moolenbroek
c3b6f8f269 Import NetBSD inetd(8)
Do not start it by default just yet.

Change-Id: Id8d2dd33eb67ae74b3ef3060638e20c781e8e37d
2017-03-09 23:40:18 +00:00
David van Moolenbroek
e044bafaad Import NetBSD telnetd(8)
Change-Id: Ie1ae80e8a4945f6f4ccce8f468c1b04a8d89cf43
2017-03-09 23:40:17 +00:00
David van Moolenbroek
7348b5c52b Import NetBSD telnet(1)
Change-Id: Ib58b43cc9baabe183a59410212827f65ec117277
2017-03-09 23:40:16 +00:00
David van Moolenbroek
72e899eafc Import NetBSD traceroute6(8)
Change-Id: I040651cf29a9efd6b85afafe6813e48c2f1a4f2d
2017-03-09 23:40:16 +00:00
David van Moolenbroek
903ca1e525 Import NetBSD ping6(8)
Change-Id: Ife49f5fac0e50852c74a0f85b6129c204d172c68
2017-03-09 23:40:15 +00:00
David van Moolenbroek
04e82b7dc9 Import NetBSD arp(8)
Behaviorally this port should already be largely on par with the
NetBSD 8 version, in that it sets the RTF_LLDATA flag on routing
socket requests to indicate that they target link-local data.

Many parts of the arp(8) functionality are currently not yet supported
by the operating system, largely due to lwIP not exposing appropriate
means of implementing them.

Change-Id: Icfac054b4deddda03eee4acf0e261aa48cd031ba
2017-03-09 23:40:14 +00:00
David van Moolenbroek
66dfcc8533 Import NetBSD netstat(1)
The port forces the use of sysctl(7), as obtaining information through
KVM is not and will never be viable.  The sysctl mode of netstat(1) is
currently somewhat limited and buggy, though.  We fix a few minimal
issues, but more improvements will have to come from NetBSD reimports.

Some of netstat(1)'s views are currently not supported by the
operating system.  Later improvements on this point will not require
changes to the imported code, though.

Change-Id: If74a6811f0fc81bd1ecc31010a28379b14b2a0eb
2017-03-09 23:40:14 +00:00
David van Moolenbroek
483e595557 Import NetBSD route(8)
Change-Id: I724a2a56157ea72afdd3f6a82239687894c8e3e8
2017-03-09 23:40:13 +00:00
David van Moolenbroek
90b801219a Import NetBSD ifconfig(8)
Not all of its functionality is actually implemented in the operating
system.  In addition, a few modules (agr, vlan) have been disabled
because we have not imported the necessary headers yet.

Change-Id: I4c9271065d640bd9112b4bd27e2652e1d51b18b4
2017-03-09 23:40:12 +00:00
David van Moolenbroek
f1fab66e7d Import NetBSD libwrap
Change-Id: Ib8b979fb9a96c2048b8ea93038944c743048bff4
2017-03-09 23:40:12 +00:00
David van Moolenbroek
c2a43b2200 Import NetBSD nsswitch.conf(5)
Change-Id: I0464b474d50b39cd6259c492e1fae6fecfd9d984
2017-03-09 23:40:11 +00:00
David van Moolenbroek
9b6c0eaf74 Import NetBSD hosts(5)
Change-Id: I0924dcc7d4eb9151b77305f370360722d4a7533a
2017-03-09 23:40:11 +00:00
David van Moolenbroek
5588c638c0 libutil: drop some MINIX-specific changes
Change-Id: I8deeac84deb4a986b62caabe96c8f7c722d97921
2017-03-09 23:40:10 +00:00
David van Moolenbroek
722c5aa73f Enable IPv6 support
Change-Id: I3f68c38ca5efbecd04941064542ed24004db1429
2017-03-09 23:40:09 +00:00
David van Moolenbroek
08cbf5a04d Enable a few more NetBSD functions
Change-Id: Ia8463adfb12b465bd43a62aee9f14b21eaa13b19
2017-03-09 23:40:09 +00:00
David van Moolenbroek
e6dabba58b PTY: add minimal support for TIOCPKT
With TIOCPKT enabled, each piece of output is preceded by a zero byte
on the PTY master.  In addition, a non-zero byte is a flags field
that conveys information about changes on the pseudoterminal.  This
patch implements the former, but not the latter.  That is enough to
get telnetd(8) going, however.  TIOCPKT support may be extended later.

Change-Id: I6ef9cc8cf1b4406147b088400fc8499684b62a30
2017-03-09 23:40:08 +00:00
David van Moolenbroek
d7c7182ad4 Retire MINIX rlogin(1)
Change-Id: Ib85e74e5333e8fffa05631dbc760284761bf3ecb
2017-03-09 23:40:08 +00:00
David van Moolenbroek
47ebcd22bd Retire MINIX rget(1), rput(1)
Change-Id: I70e3ec9281275730c589fb7683801dc1ca584cab
2017-03-09 23:40:07 +00:00
David van Moolenbroek
a9ef5b90e6 Retire MINIX in.telnetd(8)
Change-Id: Ib54998e7a81f924d19b8013ef567703996d24a03
2017-03-09 23:40:06 +00:00
David van Moolenbroek
4d04ccc15b Retire MINIX telnet(1)
..which, for some strange reason, was installed as "ttn".

Change-Id: I5ad2f969ad7978a27fb7345f8434470ca427d429
2017-03-09 23:40:06 +00:00
David van Moolenbroek
34a8cf369f Retire MINIX rarpd(8)
Change-Id: I2d7b7edbb8fa6000ba368d156cf947e7691cf454
2017-03-09 23:40:05 +00:00
David van Moolenbroek
9cf227216d Retire MINIX irdpd(8)
Change-Id: Id11c6db9db5da18346d993cb9c3faa4313ed3ed4
2017-03-09 23:40:04 +00:00
David van Moolenbroek
f130137a5e Retire MINIX arp(8)
Change-Id: I8351fbb99d73811282e46dae7fae1b6abb130bf2
2017-03-09 23:40:04 +00:00
David van Moolenbroek
b8046fb69b Retire MINIX tcpd(8)
Change-Id: If419d441c5df0b9f2e29db1ef0d904d102739f9b
2017-03-09 23:40:03 +00:00
David van Moolenbroek
fd8826c892 Retire MINIX host(1)
Change-Id: I19d2e866d6d397d3bff9ba698cb8ec26267ee82c
2017-03-09 23:40:03 +00:00
David van Moolenbroek
9490732a59 Retire MINIX dhcpd(8)
Change-Id: I4b8c738b6176ce390a7a7817b0dcaf9caffe636c
2017-03-09 23:40:02 +00:00
David van Moolenbroek
035c234ade Retire MINIX hostaddr(1)
Change-Id: I30c7b5fe4c96ea040c3eea46f1dc4d9bd135745d
2017-03-09 23:40:01 +00:00
David van Moolenbroek
407c396431 Retire MINIX nonamed(8)
Also retire support for the MINIX versions of /etc/hosts and
/etc/resolv.conf.  These files will be brought back with NetBSD
imports, although like NetBSD, MINIX 3 will be using external
resolvers directly from then on.  Since resolv.conf is hand-created
rather than installed, we do not mark it as obsolete.

Change-Id: Ie6154d5a4d8d977c19b9754bf920ae868680e9d1
2017-03-09 23:40:01 +00:00
David van Moolenbroek
50c98e1f41 Retire MINIX pr_routes(8)
Change-Id: Ic7494d097f9d19185b7173edb7590044baee5abc
2017-03-09 23:40:00 +00:00
David van Moolenbroek
73ee574be3 Retire MINIX add_route(8)
Change-Id: I900a3c6ac8e8fac15f5f84960bb89f92aeb90863
2017-03-09 23:40:00 +00:00
David van Moolenbroek
96339c07fd Retire MINIX ifconfig(8)
Change-Id: I26f3ceff01bbd31e4c009752c7454a58e8a72abf
2017-03-09 23:39:59 +00:00
David van Moolenbroek
c5da0dffe2 Retire inet: the previous MINIX TCP/IP service
This commit (temporarily) leaves MINIX 3 without a TCP/IP service.

Thanks go out to Philip Homburg for providing this TCP/IP stack in the
first place.  It has served MINIX well for a long time.

Change-Id: I0e3eb6fe64204081e4e3c2b9d6e6bd642f121973
2017-03-09 23:39:58 +00:00
David van Moolenbroek
3ea34559da Retire lwip: the previous lwIP-based TCP/IP service
Change-Id: Id9bbf96344a6e9d796f6773547588a981e70bf0f
2017-03-09 23:39:58 +00:00
David van Moolenbroek
49bf8d5c6a Retire MINIX tcpstat(1), udpstat(1)
This needs to be done before retiring inet itself, since these
utilities include headers from inet directly.

Also retire the now-obsolete paramvalue(3).

Change-Id: I9b27771190a6a32ee533b0c0d9d37f61a16ee36c
2017-03-09 23:39:57 +00:00
David van Moolenbroek
baa5830f28 tests: add advanced UDS tests (test90)
Change-Id: Ib4b81d441368fd9b7e7c7b9cab802bb01fa04065
2017-03-09 23:39:56 +00:00
David van Moolenbroek
27852ebe53 UDS: full rewrite
This new implementation of the UDS service is built on top of the
libsockevent library.  It thereby inherits all the advantages that
libsockevent brings.  However, the fundamental restructuring
required for that change also paved the way for resolution of a
number of other important open issues with the old UDS code.  Most
importantly, the rewrite brings the behavior of the service much
closer to POSIX compliance and NetBSD compatibility.  These are the
most important changes:

- due to the use of libsockevent, UDS now supports multiple suspending
  calls per socket and a large number of standard socket flags and
  options;
- socket address matching is now based on <device,inode> lookups
  instead of canonized path names, and socket addresses are no longer
  altered either due to canonization or at connect time;
- the socket state machine is now well defined, most importantly
  resolving the erroneous reset-on-EOF semantics of the old UDS, but
  also allowing socket reuse;
- sockets are now connected before being accepted instead of being
  held in connecting state, unless the LOCAL_CONNWAIT option is set
  on either the connecting or the listening socket;
- connect(2) on datagram sockets is now supported (needed by syslog),
  and proper datagram socket disconnect notification is provided;
- the receive queue now supports segmentation, associating ancillary
  data (in-flight file descriptors and credentials) with each segment
  instead of being kept fully separately; this is a POSIX requirement
  (and needed by tmux);
- as part of the segmentation support, the receive queue can now hold
  as many packets as can fit, instead of one;
- in addition to the flags supported by libsockevent, the MSG_PEEK,
  MSG_WAITALL, MSG_CMSG_CLOEXEC, MSG_TRUNC, and MSG_CTRUNC send and
  receive flags are now supported;
- the SO_PASSCRED and SO_PEERCRED socket options are replaced by
  LOCAL_CREDS and LOCAL_PEEREID respectively, now following NetBSD
  semantics and allowing use of NetBSD libc's getpeereid(3);
- memory usage is reduced by about 250 KB due to centralized in-flight
  file descriptor tracking, with a limit of OPEN_MAX total rather than
  of OPEN_MAX per socket;
- memory usage is reduced by another ~50 KB due to removal of state
  redundancy, despite the fact that socket path names may now be up to
  253 bytes rather than the previous 104 bytes;
- compared to the old UDS, there is now very little direct indexing on
  the static array of sockets, thus allowing dynamic allocation of
  sockets more easily in the future;
- the UDS service now has RMIB support for the net.local sysctl tree,
  implementing preliminary support for NetBSD netstat(1).

Change-Id: I4a9b6fe4aaeef0edf2547eee894e6c14403fcb32
2017-03-09 23:39:56 +00:00
David van Moolenbroek
241ebcae9b RMIB: expose full node path; improve restartability
A single function may be used to handle the implementation of more
than one node.  In some cases, the behavior of that function may
depend on the path name used to reach the node.  Therefore, provide
the full path name as part of the call information.

As a result, RMIB has to save the paths for each of its remote MIB
mount points.  That in turn also allows it to autonomously remount its
mount points after a MIB service restart, thus bringing us a step
closer to proper recovery after a MIB crash without requiring the
service using RMIB to perform explicit steps.  As before, the missing
ingredient is actual notification of MIB service restarts, and proper
support for *that* will likely require changes to the DS service.

Change-Id: Ic0c79931d6f3a76c2c998047f8b47350fd0fa5b0
2017-03-09 23:39:55 +00:00
David van Moolenbroek
bfa518c7ec PM/libsys: extend getepinfo, add getsockcred(3)
The service-only getepinfo(2) PM call returns information about a
given endpoint.  This patch extends that call so that it returns
enough information to allow correctly filling a sockcred structure.
A new getsockcred(3) function is added to libsys to fill an actual
sockcred structure with the obtained information.  However, for the
caller's convenience, the groups list is kept separate.

Change-Id: I9f1a6d1a221c77eabaa3498ff4ec9a5fb922e4fd
2017-03-09 23:39:55 +00:00
David van Moolenbroek
462713495a libsys: retire getnucred in favor of getepinfo
The getnucred() function was used by UDS to obtain credentials of user
processes in a form used in the UDS API, namely the ucred structure.
Since the NetBSD merge, this structure has changed drastically (aside
from being renamed to "uucred"), and it is no longer in UDS's best
interest to use this structure internally.  Therefore, getnucred() is
no longer a useful API either, and instead we directly use the
previously private getepinfo() function to obtain credentials.

Change-Id: I80bc809de716ec0a9b7497cb109d2f2708a629d5
2017-03-09 23:39:54 +00:00
David van Moolenbroek
dd96967135 UDS: prepare for socket file creation in bind(2)
This patch prepares for moving of the creation of socket files on the
file system from the libc bind(2) stub into the UDS service.  This
change is necessary for the socket type agnostic libc implementation.
The change is not yet activated - the code that is not yet used is
enclosed in "#if NOT_YET" blocks.  The activation needs to be atomic
with UDS's switch to libsockdriver; otherwise, user applications may
break.

As part of the change, various UDS bind(2) semantics are changed to
match the POSIX standard and other operating systems.  In
implementation terms, the service-only VFS API checkperms(2) is
renamed to socketpath(2), and extended with a new subcall which
creates a new socket file.  An extension to test56 checks the new
bind(2) semantics of UDS, although most new tests are still disabled
until activation as well.

Finally, as further preparation for a more structural redesign of the
UDS service, also return the <device,inode> number pair for the
created or checked file name, and make returning the canonized path
name optional.

Change-Id: I892d04b3301d4b911bdc571632ddde65fb747a8a
2017-03-09 23:39:53 +00:00
David van Moolenbroek
4c27a83389 Add libsockevent: a socket event dispatching library
This library provides an event-based abstraction model and dispatching
facility for socket drivers.  Its main goal is to eliminate any and
all need for socket drivers to keep track of pending socket calls.
Additionally, this library takes over responsibility of a number of
other tasks that would otherwise be duplicated between socket drivers,
but in such a way that individual socket drivers retain a large degree
of freedom in terms of API behavior.  The library's main features are:

- suspension, resumption, and cancellation of socket calls;
- an abstraction layer for select(2);
- state tracking of shutdown(2);
- pending (asynchronous) errors and the SO_ERROR socket option;
- listening-socket tracking and the SO_ACCEPTCONN socket option;
- generation of SIGPIPE signals; SO_NOSIGPIPE, MSG_NOSIGNAL;
- send and receive low-watermark tracking, SO_SNDLOWAT, SO_RCVLOWAT;
- send and receive timeout support and SO_SNDTIMEO, SO_RCVTIMEO;
- an abstraction layer for the SO_LINGER socket option;
- tracking of various on/off socket options as well as SO_TYPE;
- a range of pre-checks on socket calls that are required POSIX.

In order to track per-socket state, the library manages an opaque
"sock" object for each socket.  The allocation of such objects is left
entirely to the socket driver.  Each sock object has an associated
callback table for calls from libsockevent to the socket driver.  The
socket driver can raise events on the sock object in order to flag
that any previously suspended operations of a particular type should
be resumed.  The library may defer processing such raised events if
immediate processing could interfere with internal consistency.

The sockevent library is layered on top of libsockdriver, and should
be used by all socket driver implementations if at all possible.

Change-Id: I3eb2c80602a63ef13035f646473360293607ab76
2017-03-09 23:39:53 +00:00
David van Moolenbroek
85723df033 Add libsockdriver: a library for socket drivers
This library provides abstractions for socket drivers, and should be
used as the basis for all socket driver implementations.  It provides
the following functionality:

  - a function call table abstraction, hiding the details of the
    socket driver protocol with simple parameters and presenting the
    socket driver with callback functions very similar to the BSD
    socket API calls made from userland;
  - abstracting data structures and helper functions for suspending
    and resuming blocking calls;
  - abstracting data structures and helper functions for copying data
    from and to the caller.

Overall, the library is similar to lib{block,char,fs,input,net}driver
in concept.  Some of the abstractions provided here should in fact be
applied to libchardriver as well.  As always, for the case that the
provided message loop is too restrictive, a set of more low-level
message processing functions is provided.

Change-Id: I79ec215f5e195c3b0197e223636f987d3755fb13
2017-03-09 23:39:52 +00:00
David van Moolenbroek
45443f35b5 VFS: support close-on-exec flag for copyfd(2)
The flag is supported only when copying out file descriptors (i.e.
COPYFD_TO).  It will be used by UDS to support MSG_CMSG_CLOEXEC.

Change-Id: I46bfd04b5f28e22ec48938e43e42f78d3931220d
2017-03-09 23:39:51 +00:00
David van Moolenbroek
c344203e48 VFS: deny copying sockets to owning socket driver
This patch stops a socket driver from using copyfd(2) to copy in a
file descriptor that is a reference to a socket owned by that socket
driver, returning EDEADLK instead.  In effect, this will stop deadlock
and resource exhaustion issues with UDS once it has been converted to
a socket driver.  See the comment in the patch for details.

Change-Id: I5728a405eabda207725618231a6ff7be2d517146
2017-03-09 23:39:51 +00:00
David van Moolenbroek
491d647a3b VFS: support for suspending close(2) for sockets
This change effectively adds the VFS side of support for the SO_LINGER
socket option, by allowing file descriptor close operations to be
suspended (and later resumed) by socket drivers.  Currently, support
is limited to the close(2) system call--in all other cases where file
descriptors are closed (dup2, close-on-exec, process exit..), the
close operation still completes instantly.  As a general policy, the
close(2) return value will always indicate that the file descriptor
has been closed: either 0, or -1 with errno set to EINPROGRESS.  The
latter error may be thrown only when a suspended close is interrupted
by a signal.

As necessary for UDS, this change also introduces a closenb(2) system
call extension, allowing the caller to bypass blocking SO_LINGER close
behavior.  This extension allows UDS to avoid blocking on closing the
last reference to an in-flight file descriptor, in an atomic fashion.
The extension is currently part of libsys, but there is no reason why
userland would not be allowed to make this call, so it is deliberately
not protected from use by userland.

Change-Id: Iec77d6665232110346180017fc1300b1614910b7
2017-03-09 23:39:50 +00:00
David van Moolenbroek
722cbc6186 VFS: change select(2) semantics for closed filps
If a select(2) call was issued on a file descriptor for which the file
pointer was closed due to invalidation (FILP_CLOSED), typically as the
result of a character/socket driver dying, the call would previously
return with an error: EINTR upon call entry or EIO on invalidation at
at a later time.  Especially the former could severely confuse
applications, which would assume the call was interrupted by a signal,
restart the select call and immediately get EINTR again, ad infinitum.

This patch changes the select(2) semantics such that for closed filps,
the file descriptor is returned as readable and/or writable (depending
on the requested operations), as such letting the entire select call
finish successfully.  Applications will then typically attempt to read
from and/or write to the file descriptor, resulting in an I/O error
that they should generally be better equipped to handle.

This patch also fixes a potential problem with returning early from a
select(2) call if a bad file descriptor is given: previously, in such
cases not all actions taken so far would be undone; now they are.

Change-Id: Ia6581f8789473a8a6c200852fccf552691a17025
2017-03-09 23:39:50 +00:00
David van Moolenbroek
e3b8d4bb58 VFS: add BSD socket API, socket driver support
This patch adds the implementation of the BSD socket system calls
which have been introduced in an earlier patch.  At the same time, it
adds support for communication with socket drivers, using a new
"socket device" (SDEV_) protocol.  These two parts, implemented in
socket.c and sdev.c respectively, form the upper and lower halves of
the new BSD socket support in VFS.  New mapping functionality for
socket domains and drivers is added as well, implemented in smap.c.

The rest of the changes mainly facilitate the separation of character
and socket driver calls, and do not make any fundamental alterations.
For example, while this patch changes VFS's select.c rather heavily,
the new select logic for socket drivers is the exact same as for
character drivers; the changes mainly separate the driver type
specific parts from the generic select logic further than before.

Change-Id: I2f13084dd3c8d3a68bfc69da0621120c8291f707
2017-03-09 23:39:49 +00:00
David van Moolenbroek
181fb1b2b5 RS: add infrastructure for mapping socket drivers
This patch introduces the first piece of support for the concept of
"socket drivers": services that implement one or more socket protocol
families.  The latter are also known as "domains", as per the first
parameter of the socket(2) API.  More specifically, this patch adds
the basic infrastructure for specifying that a particular service is
the socket driver for a set of domains.

Unlike major number mappings for block and character drivers, socket
domain mappings are static.  For that reason, they are specified in
system.conf files, using the "domain" keyword.  Such a keyword is to
be followed by one or more protocol families, without their "PF_"
prefix.  For example, a service with the line "domain INET INET6;"
will be mapped as the socket driver responsible for the AF_INET and
AF_INET6 protocol families.

This patch implements only the infrastructure for creating such
mappings; the actual mapping will be implemented in VFS in a later
patch.  The infrastructure is implemented in service(8), RS, and VFS.

For now there is a hardcoded limit of eight domains per socket driver.
This may sound like a lot, but the upcoming new LWIP service will
already use four of those.  Also, it is allowed for a service to be
both a block/character driver and a socket driver at the same time,
which is a requirement for the new LWIP service.

Change-Id: I93352d488fc6c481e7079248082895d388c39f2d
2017-03-09 23:39:49 +00:00
David van Moolenbroek
a1c660069f libc: switch to NetBSD getifaddrs(3)
Change-Id: I698f7cef84506ebd7beed6974a232eb75ab853c3
2017-03-09 23:39:48 +00:00
David van Moolenbroek
14d921278d Import NetBSD getent(1)
Disable RPC support for now.

Change-Id: I5ccb435220bf20cd9089cdd7aacb7d126f62f119
2017-03-09 20:04:33 +01:00
Jia-Ju Bai
0d23d856eb Fix two mistakes in IP1000 driver
Change-Id: Iafdfc7496c0ed45727f414c35350cf86b644413b
2017-03-09 14:36:42 +01:00
David van Moolenbroek
8d0759b089 isofs: fix reported st_blocks stat(2) field
The st_blocks field should count 512-byte units, not file system
block units.  The previous computation would cause utilities such
as du(1), when used on isofs, to be off by a factor four.

Change-Id: If47c234079d19bd5b41f35a97780667efd822509
2017-02-26 22:22:20 +00:00
David van Moolenbroek
1d9650c9c5 etc: replace one more "service" with minix-service
This omission would cause the test set to hang, at least, if the
old /bin/service was indeed deleted.

Change-Id: I9423ecc77a4bf778973de81a49300748ce8c3dfd
2017-02-26 00:03:38 +00:00
David van Moolenbroek
8898fa503b ramdisk: clean up CD boot output
In particular, remove a stray '1'.

Change-Id: If82689060a92a4af318b01325492627944fba07f
2017-02-24 18:19:43 +00:00
David van Moolenbroek
e110411edb share: also install other existing manpages
A pair of manual pages were already present in /usr/share/man, but
not yet installed.  Install them as well.  Lots and lots more from
NetBSD's set of manual pages should be imported, though.

Change-Id: Ie2e8946967afcb2e71de563f06fa331586dcb31d
2017-02-23 14:09:01 +00:00
David van Moolenbroek
92bce86258 Import NetBSD service(8)
Change-Id: I48a4958424ebcdbd279b11e5425a6cd1b4a73121
2017-02-23 14:08:56 +00:00
David van Moolenbroek
e4449940d2 No longer auto-start pkgsrc packages
In order to comply with the pkgsrc standards, pkgsrc packages are no
longer auto-started.  Instead, we require that users follow the common
pkgsrc procedure: to start a pkgsrc package as part of system startup,
copy its startup script from /usr/pkg/etc/rc.d to /etc/rc.d, and make
the appropriate changes to /etc/rc.conf.

This change affects in particular the openssh package, of which its
ssh daemon is no longer auto-started.  However, installing this
package also no longer causes all kinds of Kerberos-related warnings
to be reported at boot time now.

Also remove a leftover reference to the defunct ddekit usb package.

Change-Id: I4d42f6ca1ab5e3bc2ec296bc7c0e3056964ae451
2017-02-23 14:08:50 +00:00
David van Moolenbroek
325ce30bcc Initial import of NetBSD rc system
IMPORTANT: this change has a docs/UPDATING entry!

This patch performs an initial import of the infrastructure and a
subset of the NetBSD set of rc startup and shutdown scripts.  The
"initial" refers to the fact that this is not yet a full switch to the
NetBSD rc system: the MINIX ramdisk rc script, which (typically) runs
as the first thing, is kept as is.  After mounting the root file
system, the ramdisk rc script will start the NetBSD rc infrastructure
by invoking /etc/rc, however.  The regular MINIX startup-and-shutdown
script has been moved from /etc/rc to /etc/rc.minix, and is now
invoked as part of the NetBSD rc infrastructure through a bridge rc
script /etc/rc.d/minixrc.  /etc/rc.minix invokes /usr/etc/rc as before.

Switching over the ramdisk to the NetBSD system and decomposing the
MINIX rc.minix script into smaller components are left to future work.
Also, the current pkgsrc etc/rc.d auto-start functionality is left as
is, even though it should be removed (see the etc/usr/rc comment).

Change-Id: Ia96cae7c426e94b85c67978dc1307dacc4b09fc5
2017-02-23 14:08:39 +00:00
David van Moolenbroek
2109df2759 VM: fix race condition communicating with VM
After processing certain asynchronous requests from VFS, VM would send
an asynchronous reply without supplying the AMF_NOREPLY flag.  As a
result, this asynchronous reply could be taken as the result of an
ipc_sendrec() call, causing the entire VM/VFS communication to become
desynchronized.  The end result was a deadlock-induced panic during a
later request.

This bug was exposed because of the higher-than-usual concurrency
level in the NetBSD rc scripts.  The fix consists of properly setting
the AMF_NOREPLY flag for asynchronous replies.

Change-Id: Iafafe2fdd67f212ecbf27a53862cefba2e4cf7e8
2017-02-23 11:27:42 +00:00
David van Moolenbroek
3e1f70db42 VBOX: update current time immediately at startup
Performing the update at any later time may cause rc scripts to work
with a wrong date, which may have side effects, such as databse files
getting regenerated on every boot.

Change-Id: Idfdbf67ad285300c982d95769007dc88c522b908
2017-02-22 17:18:12 +00:00
David van Moolenbroek
81fc6023c2 Import NetBSD services_mkdb(8)
Change-Id: Ia3fc2479d2abb2dbe9afd1b60e0ffbaf377bcf5a
2017-02-22 17:18:06 +00:00
David van Moolenbroek
5ae330e220 Import NetBSD fmt(1)
This requires importing a few files from mail(1) already.  Importing
the rest of mail(1) is left to future work.

Change-Id: If96513a306245cd7fb64660758d0dbd29a36e87c
2017-02-22 17:18:00 +00:00
David van Moolenbroek
045e0ed35c Import NetBSD rcorder(8)
Change-Id: Id2ed4959f8089189929fc56401d1c70add5ad323
2017-02-22 17:17:28 +00:00
David van Moolenbroek
c58da9fbc3 Rename MINIX service(8) to minix-service(8)
IMPORTANT: this change has a docs/UPDATING entry!

This rename is unfortunately necessary because NetBSD has decided to
create its own service(8) utility, and we will want to import theirs
as well.  The two can obviously not coexist.

Also move ours from /bin to /sbin, as it is a superuser-only utility.

Change-Id: Ic6e46ffb3a84b4747d2fdcb0d74e62dbea065039
2017-02-22 17:16:21 +00:00
David van Moolenbroek
bf5536d653 distrib: more minor fixes
- unbreak MKDEBUGLIB=yes builds
- please do not delete my .exrc file :(

Change-Id: Ib1d40e6894062bd881e50c712da88e7a604f2ad7
2017-02-22 13:57:54 +00:00
David van Moolenbroek
77e79d3374 etc: synchronize master.password, group to NetBSD
IMPORTANT: this change has a docs/UPDATING entry!

This change is a long overdue switch-over from the old MINIX set of
user and group accounts to the NetBSD set.  This switch-over is
increasingly important now that we are importing more and more
utilities from NetBSD, several of which expect various user accounts
to exist.  By switching over in one go, we save ourselves various
headaches in the long run, even if the switch-over itself is a bit
painful for existing MINIX users.

The newly imported master.passwd and group files have three exceptions
compared to their NetBSD originals:

1. There is a custom "service" account for MINIX 3 services.  This
   account is used to limit run-time privileges of various system
   services, and is not used for any files on disk.  Its user ID may
   be changed later, but should always correspond to whatever the
   SERVICE_UID definition is set to.
2. The user "bin" has its shell set to /bin/sh, instead of NetBSD's
   /sbin/nologin.  The reason for this is that the test set in
   /usr/tests/minix-posix will not be able to run otherwise.
3. The group "operator" has been set to group ID 0, to match its old
   value.  This tweak is purely for transitioning purposes: as of
   writing, pkgsrc packages are still using root:operator as owner and
   group for most installed files.  Sometime later, we can change back
   "operator" to group ID 5 without breaking anything, because it does
   not appear that this group name is used for anything important.

Change-Id: I689bcfff4cf7ba85c27d1ae579057fa3f8019c68
2017-02-18 21:37:24 +00:00
David van Moolenbroek
e436e99481 distrib: fix entries that are off
This small change makes it easier to do sorts without having to deal
with these entries over and over again.

Change-Id: Id5077a17733fa4b535cdc9881109286335d3cb17
2017-02-18 12:37:22 +00:00
David van Moolenbroek
0c6b4c6127 printconfig(8): print PCI sub-VID/DID when set
In order to allow for proper matching of available drivers to system
hardware, the output of this utility should reflect the full details
of the input from configuration files.  In particular, that includes
sub-IDs of PCI devices when those have been specified.

Change-Id: Iea24d72795cd714268dbdb95df998eb74de8f2bd
2017-02-16 10:22:28 +00:00
David van Moolenbroek
5f6c420586 Retire env.h
This was a MINIX3-specific header file placed outside of the minix/
header subdirectory, with its definitions duplicated in the more
standard minix/sysutil.h header.

Also make env_prefix(3) take constant pointers.

Change-Id: I243c38eb38e24eb98f0c0dddf7f340e7fec255f4
2017-02-16 10:22:27 +00:00
David van Moolenbroek
40dec70c39 trace(1): print sin6_scope_id when relevant
Site-local addresses are out, as they are RFC-deprecated and not
supported on MINIX 3 at all.  Interface-local and link-local multicast
addresses are in, because they are relevant in the context of a
particular zone ID only.

Change-Id: I64a9ecb472946f717f27a72c4073d78aa1120508
2017-02-16 10:21:56 +00:00
David van Moolenbroek
44fdeb7a62 libc: more poll(3) wrapper fixes
- POLLRDBAND is reported by select(2) as errorfd, not readfd;
- POLLERR is not the same as errorfd of select(2);
- flags that are not requested should not be returned.

Change-Id: I9cb3c2c260ead5a2852a2fbbc10280c2b5b0dff9
2017-02-16 10:18:26 +00:00
FeZoli
68804c208e Added Hungarian keyboard layout
Change-Id: Ib52ad3723ba6679506128813be962fd68f8998c5
2017-02-08 22:51:26 +01:00
Jia-Ju Bai
c28d8fefcf VT6105: Restructure the code and correct function order in initialization
Change-Id: Ibbc8f835174349501e74dde7163c234effb34bc8
2017-01-26 12:50:48 +01:00
Jia-Ju Bai
3afdc1200b IP1000: Restructure the code and correct function order in initialization
Change-Id: I7c887a777205ea0ae38b4ef1830535d035c5a976
2017-01-26 12:47:45 +01:00
Jean-Baptiste Boric
72e11e2789 Import NetBSD's passwd.conf
Without this file, the NetBSD userland will fall back by default to the
old, insecure classic UNIX password hashing algorithm.

This is a big security issue. Please check docs/UPDATING for details.

Change-Id: Ib85646ee4678f91384bab238426ee55ff26da011
2017-01-22 20:43:54 +01:00
Jia-Ju Bai
eecf6d233d Add the driver for Trident 4DWAVE-DX sound card
Change-Id: I6a4f5427915032a6a4c0246fed35c10397df3e07
2017-01-08 19:01:58 +01:00
Jia-Ju Bai
8acfcfc39e Add the driver for CS4281 sound card
Change-Id: Ifc1b7c129578c5efa5e328664d10d07ee5df786b
2017-01-08 19:01:20 +01:00
Jia-Ju Bai
86fd71a2c9 Add the driver for ALS4000 sound card
Change-Id: I2ad08e8479b743ec235d1c9e541faa2fa6a29fcc
2017-01-08 19:00:40 +01:00
Jia-Ju Bai
37e23b1cc7 Add the driver for CMI8738 sound card
Change-Id: I5a53e3b8652a014e105ca7c77c42a730f6824307
2017-01-08 18:59:39 +01:00
David van Moolenbroek
6dd801ffb8 libaudiodriver: buffer accounting bugfix
This fixes #191.

Change-Id: I93752161e466b2d03bbcb0838705aab9619c05c8
2016-12-28 13:12:58 +00:00
David van Moolenbroek
192c3a97f6 libaudiodriver: readd callback to drv_int_sum()
The callback, which was dropped in commit git-842c4ed, allows drivers
to fetch the interrupt status once and save it locally for subsequent
calls to drv_int().

This fixes #190 .

Change-Id: I83918656f637e716f60e9f4c19f1498f761d3b52
2016-12-28 13:08:23 +00:00
David van Moolenbroek
10a44c0ee2 trace(1): add basic support for timestamps
This patch adds strace-like support for a -t command line option,
which causes a timestamp to be printed at the beginning of each line.
If the option is given more than once, the output will also include
microseconds.

Change-Id: I8cda581651859448c154b01815cc49d915b7b354
2016-12-28 13:06:04 +00:00
David van Moolenbroek
1bb466dd36 libc: make posix_spawn(3) clean up child on failure
Change-Id: I39a321f23326485fca789e5792a57532d1036716
2016-12-28 13:05:55 +00:00
David van Moolenbroek
b52b83f927 test74: allow to be run from source directory
A small fix to allow this test to be run from its original source
directory location, in addition to its installed location.

Change-Id: I4b7afed14ba02b1bea8d9c5f65bc96698a279188
2016-12-28 13:05:44 +00:00
Antoine Leca
3f862305f8 Fix the process for GNU tools on MINIX
This is a fix over commit a150b26ee8
On a MINIX station, the tools are not usually built and
on a first-time building of the tree, the fetching script
of texinfo was not triggered in some cases. Let force it.
Reported on minix3 googlegroup by Chris Card.

Change-Id: I8beafdeaec66bb1f1f3250bd64c1e14c0023e9d0
2016-11-30 08:42:36 +01:00
117b6ea003 Fix OPSYS constant in pkg_install tools
Change-Id: I84c1596e4ca9b5a016b628deb75c8133d51a6a75
2016-11-30 08:35:38 +01:00
Jia-Ju Bai
8d98f2e579 Add the driver for IC Plus 1000A Ethernet card
Change-Id: I9ac119c6285bc63a8b795b44d9ab7d245d9a8832
2016-11-24 17:22:28 +01:00
Jia-Ju Bai
8dc24c0650 Update vt6105
Change-Id: I8136a17eb47f626141bb20b9d6a30f82117425b7
2016-11-24 17:22:15 +01:00
rlfnb
fee60e45e6 introducing libacpi
Change-Id: I0808545fefaefc9a8fc8d1101bd85b676467fea0
2016-10-29 17:08:10 +02:00
rlfnb
e154914956 Added vendor- and device id for Via Rhine III
The device id added is used by ALIX boards.

Change-Id: I78d1ce9f2fa0ee121e68d2c84818f669eeab3092
2016-10-24 14:20:37 +02:00
Jia-Ju Bai
9784113fda vt6105: add a README file
Change-Id: I8dbb122afc130f2f2504743fa4fcbada5c97dff5
2016-10-24 14:18:54 +02:00
David van Moolenbroek
286d266fd0 PM: fix alarm signal delivery
As of change git-87c599d, when processing CLOCK notifications, PM no
longer set the current process pointer 'mp'.  That pointer is however
used when delivering signals through check_sig(), to see whether the
current process may deliver a signal to the target process.  As a
result, delivering SIGALARM signals used a previous pointer in these
checks, causing alarm signals not to be delivered in some cases.
This patch ensures that alarm signals are again delivered with PM as
current process.

Change-Id: I94ccbe8b71289df0e1d6d67928e55297bbc28360
2016-10-24 12:11:52 +00:00
David van Moolenbroek
dd41186aac libc: remove MINIX3 restrictions from getnameinfo(3)
Change-Id: I4679f6804f229520d6399a06a5da0655f2bfd899
2016-10-24 12:11:07 +00:00
David van Moolenbroek
f221d2ce48 RMIB: add support for vector copy-out
Change-Id: I9e9b4b8d6eed39fdb511c6bd2a375ddf898064a5
2016-10-24 12:10:34 +00:00
io12
9f11521a37 Fix grammar errors in a comment
Change-Id: I0ad2b6a28afb44e42d1830f1b0944579dc032261
2016-10-19 23:51:07 +02:00
Jia-Ju Bai
022136b354 Add the driver for VIA Technology 6105/6106S Ethernet card
Change-Id: I690c34f0a37bcbb20a5b7748e3dd315707460caf
2016-10-19 21:54:58 +02:00
rlfnb
702ec7400f fixed git checkout and updated latest known changeset working for grub
Change-Id: If4a1e8bfb42a20cf50d847105cc8f96c3cf1cd00
2016-10-18 14:22:28 +02:00
Richard Sailer
a0814afb2e VFS: Convert K&R C -> ANSI C
Aditionally this removes all trailing whitespaces
using: sed -i 's/[[:space:]]*$//' *.c

Change-Id: I88451fdb6f6e79e61f8aae5bd5a7f2e3538f9944
2016-10-18 14:20:21 +02:00
Richard Sailer
4aa48abab9 is: Convert K&R C -> ANSI C
Aditionally this removes all trailing whitespaces
using: sed -i 's/[[:space:]]*$//' *.c

Change-Id: I274fccee9ec320e474ac26fbe19f3bd50bec271a
2016-10-18 14:19:48 +02:00
David van Moolenbroek
6956dd2b51 libc: bugfixes for minix's poll(3) wrapper
- clear "revents" fields even when the call times out;
- do not call FD_ISSET with a negative file descriptor number.

Change-Id: I7aeaae79e73e39aed127a75495ea08256b18c182
2016-10-18 14:18:41 +02:00
David van Moolenbroek
3ac58492b3 Add LLVM GCOV coverage support
With this patch, it is now possible to generate coverage information
for MINIX3 system services with LLVM.  In particular, the system can
be built with MKCOVERAGE=yes, either with a native "make build" or
with crosscompilation.  Either way, MKCOVERAGE=yes will build the
MINIX3 system services with coverage profiling support, generating a
.gcno file for each source module.  After a reboot it is possible to
obtain runtime coverage data (.gcda files) for individual system
services using gcov-pull(8).  The combination of the .gcno and .gcda
files can then be inspected with llvm-cov(1).

For reasons documented in minix.gcov.mk, only system service program
modules are supported for now; system service libraries (libsys etc.)
are not included.  Userland programs are not affected by MKCOVERAGE.

The heart of this patch is the libsys code that writes data generated
by the LLVM coverage hooks into a serialized format using the routines
we already had for GCC GCOV.  Unfortunately, the new llvm_gcov.c code
is LLVM ABI dependent, and may therefore have to be updated later when
we upgrade LLVM.  The current implementation should support all LLVM
versions 3.x with x >= 4.

The rest of this patch is mostly a light cleanup of our existing GCOV
infrastructure, with as most visible change that gcov-pull(8) now
takes a service label string rather than a PID number.

Change-Id: I6de055359d3d2b3f53e426f3fffb17af7877261f
2016-09-24 22:18:31 +00:00
rlfnb
92dfb2dc8e Removed redundant ifdef
Change-Id: Ifb7df30591d658700d6293632f5f944c32376fdf
2016-09-10 13:44:04 +02:00
Antoine Leca
2aa07764b8 [boot-i386] Reduce differences with NetBSD
Change-Id: I50c183d283858a098f0766cf3053fa6e78ce06ad
2016-09-10 12:47:42 +02:00
Antoine Leca
7a3aae8b5b Adjust .gitignore for MINIX file system
Some files in LLVM have more than Minix-maximum of 60 characters.
Also drop some obsolete stuff, and add obj which are symlinks added
to every directory when using /usr/obj as OBJDIR (hinted in wiki.)

Change-Id: Iac82bb064f68689f247a2ee1b1d2f365344ab793
2016-09-10 12:47:03 +02:00
Jean-Baptiste Boric
6afe26749a Enable building with MKDEBUG and MKDEBUGLIB
The way these options work is by creating files that contain debugging
symbols and stashing them in a dedicated set. The minix-debug set has
been created for this purpose, but it will probably have to be refined
since it has been tested only with the default options with an i386
cross-build.

LSC: Amended to support many combination of MKDEBUG, MKDEBUGLIB, with
     and without X11, for both intel and arm.

Change-Id: I2901952e8229938f9ac79c8656484acf704ccd9b
2016-09-10 12:42:45 +02:00
Antoine Leca
a150b26ee8 Improve the process for GNU tools
Split the process to fetch GNU tools (until now embedded
within tools/Makefile.gnuhost) into a new Makefile.fetchgnu,
MINIX-specific hence relocated, which is to be also used
to fetch sources even when not building the tools.
Use it for binutils too.
Improve documentation.

Also do not run configure on each run when MKUPDATE=yes
The .WAIT serialization instruction between fetching and other
configure sources was raising a new run of configure at each
compilation. Avoid it by using two rules.

Change-Id: Ie24950ccbb5c5067f3c1ea57b7bd8294e4c9445e
2016-09-01 21:16:13 +02:00
Antoine Leca
76c7f3dac9 Obey HAVE_GOLD=no to no intent to build gold
This is useful when the host C++ compiler is broken or not compliant.

Change-Id: I09933e81ae07e95e5696b177cd4670cab33ce6c1
2016-09-01 07:47:09 +02:00
Antoine Leca
00e393ca04 Kyua framework does not build up with /usr/obj
Reported to NetBSD as PR/51389, fix by dholland
http://gnats.netbsd.org/51389

Change-Id: Ib31662000255a62261fb461fcab2d931faa47f70
2016-08-31 18:27:05 +02:00
Antoine Leca
6ddb33542a Allow repartition(8) subpartitions above 4G
Change-Id: I058ab3b58b2e7822b59365b1ce222c5588f442cd
2016-08-06 10:52:38 +02:00
rlfnb
3c71801e8e made PAE enabled by accident and fixed libmagicrt.h
Change-Id: Ia09d8b9a68aa2e1522d66ed93453de9d7d802cb2
2016-08-06 10:52:09 +02:00
David van Moolenbroek
3083d603ba Resolve a number of GCC-generated warnings
The warnings in test47 seem to be a symptom of a larger problem,
i.e., not an issue with the test set code but rather with the GCC
configuration.  Hopefully the switch to LLVM will resolve those.

Change-Id: Ic9fa3b8bc9b728947c993f2e1ed49d9a3b731344
2016-08-05 16:24:04 +02:00
David van Moolenbroek
82de0a47ea system.conf: clean up the last sys_int86 remnants
The remaining entries produced warnings at startup.

Change-Id: I076f73a813f7c3ecb208cc458939afc6c4fe3066
2016-08-05 11:17:48 +00:00
David van Moolenbroek
f83d70a503 tests: fix bug in sys_vumap test
Ever since a VM allocation strategy change, this test is fully
dysfunctional.  It should be repaired and added to the regular
test set, but that will require some work.

For now, keep it in reasonable shape.

Reported by dcb314.

This closes #153.

Change-Id: Ia57bdfdf6a3fc8d47cae76a0be9881fb4d796f6d
2016-08-05 11:17:37 +00:00
David van Moolenbroek
815afbad33 libmthread: resolve memory leaks on exception path
If libmthread runs into a memory allocation failure while attempting
to enlarge its thread pool, it does not free up any preliminary
allocations made so far.

Reported by dcb314.

This closes #152.

Change-Id: Ib882a4544e4802a0eb0a53446b43997876cde633
2016-08-05 11:17:30 +00:00
David van Moolenbroek
ab712d1923 commands: fix various small issues
Reported by dcb314.  Recommendations adopted as is.

This closes #137, closes #138, closes #139, and hopefully I got that
right this time.

Change-Id: I79774f4c398495dba19dec43fbc3f79afd186843
2016-08-05 11:17:19 +00:00
David van Moolenbroek
1ccb488d84 libsys: fix format specifier in RMIB code
Reported by dcb314.

This closes #141.

Change-Id: I26011870891f5ba22844c335af6081ee9f05c12c
2016-08-05 11:16:43 +00:00
David van Moolenbroek
89a4204b83 VFS: split block, character device handling
All functions prefixed with bdev_ are moved into bdev.c, and those
prefixed with cdev_ are now in cdev.c.  The code in both files are
converted to KNF.  The little (IOCTL-related) code left in device.c
is also cleaned up but should probably be moved into other existing
source files.  This is left to a future patch.  In general, VFS is
long overdue for a source code rebalancing, and the patch here is
only a step in the right direction.

Change-Id: I2fb25734b5778b44f2ff6d2ce331a8e2146e20b0
2016-08-05 11:16:30 +00:00
David van Moolenbroek
232819dd49 VFS: store process suspension state as union
Previously, VFS would use various subsets of a number of fproc
structure fields to store state when the process is blocked
(suspended) for various reasons.  As a result, there was a fair
amount of abuse of fields, hidden state, and confusion as to
which fields were used with which suspension states.

Instead, the suspension state is now split into per-state
structures, which are then stored in a union.  Each of the union's
structures should be accessed only right before, during, and right
after the fp_blocked_on field is set to the corresponding blocking
type.  As a result, it is now very clear which fields are in use
at which times, and we even save a bit of memory as a side effect.

Change-Id: I5c24e353b6cb0c32eb41c70f89c5cfb23f6c93df
2016-08-05 11:15:15 +00:00
David van Moolenbroek
0eb6caa076 VFS: disallow opening files of unsupported types
Any attempt to use open(2) to open a socket file now fails with
EOPNOTSUPP, as is common and in the process of being standardized.
The behavior and error code is now tested in test56.

Any attempt to open a file of which the type is not known to VFS
(e.g., as a result of bogus file system contents) now fails with EIO.
For now, this is a safety feature, to prevent VFS tripping over such
types in unchecked cases.  In the future, a proper VFS code audit
should determine whether we can lift this restriction again, although
it does not seem particularly useful to be able to open files of
unknown types anyway.  Another error code may be assigned to this case
later, too.

Change-Id: Ib4cb4341eec954f0448fe469ecf28bd78edebde2
2016-08-05 11:14:29 +00:00
David van Moolenbroek
63faa8fe9a VFS: add debug dump for select
By now it has become clear that the VFS select code has an unusually
high concentration of bugs, and there is no indication that any form
of convergence to a bug-free state is in sight.  Thus, for now, it
may be helpful to be able to dump the contents of the select tables
in order to track down any bugs in the future.  Hopefully that will
allow the next bugs to be resolved slightly after than before.

The debug dump can be triggered with "svrctl vfs get print_select".

Change-Id: Ia826746dce0f065d7f3b46aa9047945067b8263d
2016-08-05 11:14:09 +00:00
David van Moolenbroek
2ff64318e2 VFS: fix race condition in select(2)
A select query could deadlock if..

- it was querying a character or socket device that, at the start of
  the select query, was not known to be ready for the requested
  operations;
- this device could not be checked immediately, due to another ongoing
  query to the same character or socket driver;
- the select query had a timer that triggered before the device could
  be checked, thereby changing the select query to non-blocking.

In this situation, a missing flag check would cause the select code to
conclude erroneously that the operations which it flagged for later,
were satisfied.  At the same time, the same flag remained set, so that
the select query would continue to wait for that device.  This
resulted in a deadlock.  The same bug could most likely be triggered
through other scenarios that were even less likely to occur.

This patch fixes the race condition and puts in a hopefully slightly
more informative comment for the affected block of code.

In practice, the bug could be triggered fairly reliably by generating
lots of output in tmux.

Change-Id: I1c909255dcf552e6c7cef08b0cf5cbc41294b99c
2016-08-05 11:13:59 +00:00
David van Moolenbroek
a758ec672e VFS: forbid mknod(2) on symlinks
As imposed by POSIX.

Extend a random test to verify this behavior.

Change-Id: Ib70550cefaeb9efd54e22312425263a5606fb5e8
2016-08-05 11:13:38 +00:00
David van Moolenbroek
cfd712b424 Various timer improvements
Now that clock_t is an unsigned value, we can also allow the system
uptime to wrap.  Essentially, instead of using (a <= b) to see if time
a occurs no later than time b, we use (b - a <= CLOCK_MAX / 2).  The
latter value does not exist, so instead we add TMRDIFF_MAX for that
purpose.

We must therefore also avoid using values like 0 and LONG_MAX as
special values for absolute times.  This patch extends the libtimers
interface so that it no longer uses 0 to indicate "no timeout".
Similarly, TMR_NEVER is now used as special value only when
otherwise a relative time difference would be used.  A minix_timer
structure is now considered in use when it has a watchdog function set,
rather than when the absolute expiry time is not TMR_NEVER.  A few new
macros in <minix/timers.h> help with timer comparison and obtaining
properties from a minix_timer structure.

This patch also eliminates the union of timer arguments, instead using
the only union element that is only used (the integer).  This prevents
potential problems with e.g. live update.  The watchdog function
prototype is changed to pass in the argument value rather than a
pointer to the timer structure, since obtaining the argument value was
the only current use of the timer structure anyway.  The result is a
somewhat friendlier timers API.

The VFS select code required a few more invasive changes to restrict
the timer value to the new maximum, effectively matching the timer
code in PM.  As a side effect, select(2) has been changed to reject
invalid timeout values.  That required a change to the test set, which
relied on the previous, erroneous behavior.

Finally, while we're rewriting significant chunks of the timer code
anyway, also covert it to KNF and add a few more explanatory comments.

Change-Id: Id43165c3fbb140b32b90be2cca7f68dd646ea72e
2016-08-05 11:12:44 +00:00
rlfnb
bf609e1012 Preparations for PAE support
Change-Id: I9a7c9ed9f803e2e26d745d14149a8aec64ab0c75
2016-08-04 09:24:42 +02:00
Antoine Leca
e70e5a1722 Adapt MINIX-specific part of tools/installboot
This is necessary to enable correct compilation of the tools version
of installboot_nbsd(8)when cross-compiling on a system close enough
to MINIX, like NetBSD 7.0.1 for example.

Change-Id: I7a12614518293e05d64d7cc189c62651fdc64734
2016-08-03 08:09:00 +02:00
Antoine Leca
55a5a21b97 Clean up traces from long-gone sys_int86 interface
Change-Id: I773ab67342be852cc74f76b4fcbb338c9cb11f7e
2016-07-20 19:00:44 +02:00
Antoine Leca
a2bd2caf02 Drop obsolete postinstall script
Conflicts with NetBSD /usr/sbin/postinstall(8)

Change-Id: Iaefe4494b95b46d1134f4a477798765bbcc66c70
2016-07-20 17:35:49 +02:00
Antoine Leca
4aaaf2c612 Remove long-obsolete pwdauth(8) command (in usr/lib)
Change-Id: I454d506199ce1d5d48295bca86b590ce0701dcc2
2016-07-20 17:35:37 +02:00
Antoine Leca
7eb1c60ab5 Allow part(8) to make subpartitions above 4G
Change-Id: I3fd2c5de7cbb190b857eb34f16463f67a30118a3
2016-07-14 12:34:41 +02:00
36dcc4a4a9 Import locale tools and ressource files
This commit requires special steps, please checkout docs/UPDATING.

Tools:
 - gencat
 - locale
 - mkcsmapper
 - mkesdb
 - mklocale

Libs:
 - i18n_module
 - libintl

Ressources:
 - i18n
 - locale

Change-Id: I559d0399d8e98bcee15225cab786e43f31506207
2016-07-09 12:18:33 +02:00
733a844ac6 kernel/cpulocals.h: Simplify macros
Change-Id: Ice845fb0743ff686398293cef2620f5ac9c902ad
2016-07-09 12:18:15 +02:00
7eaefc5e7c gnu/texinfo: Disable -Werror for clang
Change-Id: Ib5053044c03503942f9626703f086ee2bbb518ac
2016-07-09 12:11:26 +02:00
Richard Sailer
637f688f0d PM: Convert K&R C -> ANSI C
Aditionally this removes all trailing whitespaces in pm server code
using: sed -i 's/[[:space:]]*$//' *.c

Change-Id: Ie44162fd56cd7042f4f0cc7bd7314b17ea128761
2016-07-08 21:24:33 +02:00
Ralf Neeb
1717959aeb made minix3 bootable via EFI
Change-Id: I61d995e240deb6ebb3027d3ab07e6e3759e52b01
2016-07-02 13:43:03 +02:00
Mark Pauley
03de4d97b4 Typo in hardfloat command-line fixup/replacement
- Added two missing '%' characters to replacement strings.

Change-Id: I139d432f5cf2651642284fa39112b66f478dadce
2016-07-02 13:18:46 +02:00
David van Moolenbroek
764cd267a7 INET/LWIP: minimal net.route sysctl support
At a point not too far in the future, we will be switching from the
hardcoded MINIX3 implementation of the getifaddrs(3) libc routine to
the proper NetBSD implementation.  The latter uses the
net.route.rtable sysctl functionality to obtain its information.  In
order make the transition as painless as possible, this patch adds
basic support for that net.route.rtable functionality to INET and
LWIP, using the remote MIB (RMIB) facility.

Change-Id: I54f5cea7985f6606e317c73a5e6be3a5d07bc7dc
2016-06-18 12:47:30 +00:00
David van Moolenbroek
534584945c IPC: use RMIB to handle kern.ipc sysctl subtree
With this patch, the IPC service is changed to use the new RMIB
facility to register and handle the "kern.ipc" sysctl subtree itself.
The subtree was previously handled by the MIB service directly.  This
change improves locality of handling: especially the
kern.ipc.sysvipc_info node has some peculiarities specific to the IPC
service and is therefore better handled there.  Also, since the IPC
service is essentially optional to the system, this rearrangement
yields a cleaner situation when the IPC service is not running: in
that case, the MIB service will expose a few basic kern.ipc nodes
indicating that no SysV IPC facilities are present.  Those nodes will
be overridden through RMIB when the IPC service is running.

It should be easier to add the remaining (from NetBSD) kern.ipc nodes
as well now.

Test88 is extended with a new subtest that verifies that sysctl-based
information retrieval for semaphore sets works as expected.

Change-Id: I6b7730e85305b64cfd8418c0cc56bde64b22c584
2016-06-18 12:47:24 +00:00
David van Moolenbroek
6f3e0bcd3d MIB/libsys: support for remote MIB (RMIB) subtrees
Most of the nodes in the general sysctl tree will be managed directly
by the MIB service, which obtains the necessary information as needed.
However, in certain cases, it makes more sense to let another service
manage a part of the sysctl tree itself, in order to avoid replicating
part of that other service in the MIB service.  This patch adds the
basic support for such delegation: remote services may now register
their own subtrees within the full sysctl tree with the MIB service,
which will then forward any sysctl(2) requests on such subtrees to the
remote services.

The system works much like mounting a file system, but in addition to
support for shadowing an existing node, the MIB service also supports
creating temporary mount point nodes.  Each have their own use cases.
A remote "kern.ipc" would use the former, because even when such a
subtree were not mounted, userland would still expect some of its
children to exist and return default values.  A remote "net.inet"
would use the latter, as there is no reason to precreate nodes for all
possible supported networking protocols in the MIB "net" subtree.

A standard remote MIB (RMIB) implementation is provided for services
that wish to make use of this functionality.  It is essentially a
simplified and somewhat more lightweight version of the MIB service's
internals, and works more or less the same from a programmer's point
of view.  The most important difference is the "rmib" prefix instead
of the "mib" prefix.  Documentation will hopefully follow later.

Overall, the RMIB functionality should not be used lightly, for
several reasons.  First, despite being more lightweight than the MIB
service, the RMIB module still adds substantially to the code
footprint of the containing service.  Second, the RMIB protocol not
only adds extra IPC for sysctl(2), but has also not been optimized for
performance in other ways.  Third, and most importantly, the RMIB
implementation also several limitations.  The main limitation is that
remote MIB subtrees must be fully static.  Not only may the user not
create or destroy nodes, the service itself may not either, as this
would clash with the simplified remote node versioning system and
the cached subtree root node child counts.  Other limitations exist,
such as the fact that the root of a remote subtree may only be a
node-type node, and a stricter limit on the highest node identifier
of any child in this subtree root (currently 4095).

The current implementation was born out of necessity, and therefore
it leaves several improvements to future work.  Most importantly,
support for exit and crash notification is missing, primarily in the
MIB service.  This means that remote subtrees may not be cleaned up
immediately, but instead only when the MIB service attempts to talk
to the dead remote service.  In addition, if the MIB service itself
crashes, re-registration of remote subtrees is currently left up to
the individual RMIB users.  Finally, the MIB service uses synchronous
(sendrec-based) calls to the remote services, which while convenient
may cause cascading service hangs.  The underlying protocol is ready
for conversion to an asynchronous implementation already, though.

A new test set, testrmib.sh, tests the basic RMIB functionality.  To
this end it uses a test service, rmibtest, and also reuses part of
the existing test87 MIB service test.

Change-Id: I3378fe04f2e090ab231705bde7e13d6289a9183e
2016-06-18 12:46:59 +00:00
David van Moolenbroek
53d2fa057e Do not hide the MSG_NOSIGNAL flag
Instead, filter it in libc for old networking implementations, as
those do not support sending SIGPIPE to user processes anyway.  This
change allows newer socket drivers to implement the flag as per the
specification.

Change-Id: I423bdf28ca60f024a344d0a73e2eab38f1b269da
2016-06-18 12:20:48 +00:00
David van Moolenbroek
8bda47ed96 LWIP: fix system.conf file
Change-Id: I0f204a14776b4c3aaab4723c14a508506187acbc
2016-06-18 12:20:47 +00:00
David van Moolenbroek
ebe9f48d04 Import a subset of PF distribution files
We do not support any PF functionality, nor do we intend to.  However,
some NetBSD utilities rely on the presence of these files.  Not all of
the files are installed.  The NetBSD source seems rather inconsistent
in where from to include these files.  We simply follow what NetBSD
does, though.

Change-Id: Ib244dfcc60b16ebc4697af22f71b7e014374b855
2016-06-18 12:20:46 +00:00
David van Moolenbroek
37274f3cdb Import additional networking headers from NetBSD
While still a small subset of the NetBSD headers, this set should
allow various additional utilities to be compiled without too many
MINIX3-specific changes (even if those utilities will not yet work).

Change-Id: Idc70e9901d584e960cd406f75f561dcc9a4ddb7d
2016-06-18 12:20:46 +00:00
David van Moolenbroek
91d0779762 libchardriver: make some pointers constant
Change-Id: Ieabc6962d10f9f6e0db7807fd24add212bcfc148
2016-06-18 12:20:45 +00:00
Jacob Adams
4cb315c484 kernel: Update copyright year
Change-Id: If566bf95db32d9f5ebf1a6677acdaad1c023112e
2016-06-18 12:19:59 +00:00
David van Moolenbroek
4d3708913c cawf(1): remove various redundant comparisons
Reported by dcb314.

This fixes #135, #136.

Change-Id: I0f83a92e18adf68e5ad493b9057d093a6b37b328
2016-06-17 20:09:08 +00:00
David van Moolenbroek
dc2c582f36 Correct bad assignments in various conditions
Reported by dcb314.

This fixes #128, #129, #130, #131, #132, #133.

Change-Id: I284d6dd87fba7c5775bea22d04412d685a2ab027
2016-06-17 20:07:55 +00:00
David van Moolenbroek
ee0384891a MFS: do not crash when reading superblock fails
While MFS failing to do I/O on a block is generally fatal, reading
the superblock at mount time is an exception: this case may occur
when the given partition is too small to contain the superblock.
Therefore, MFS should not crash or even report anything in this
case, but rather refuse to mount cleanly.

This fixes #121.

Change-Id: I11326b48922a0e0ebefecbb8eec7c428f985f2b3
2016-06-17 19:48:20 +00:00
David van Moolenbroek
6c7e614940 SEF: identity transfer only after controlled crash
Transparent (endpoint-preserving) restarts with identity transfer
are meant to exercise the crash recovery system only.  After *real*
crashes, such restarts are useless at best and dangerous at worst,
because no state integrity can be guaranteed afterwards.  Thus,
except after a controlled crash, it is best not to perform such
restarts at all.  This patch changes SEF such that identity transfer
is successful only if the old process was the subject of a crash
induced through "service fi".  As a result, testrelpol.sh should
continue to be able to use identity transfers for testing purposes,
but any real crash will be handled more appropriately.

This fixes #126.

Change-Id: Idc17ac7b3dfee05098529cb889ac835a0cd03ef0
2016-06-17 18:19:25 +00:00
David van Moolenbroek
7d0647db6a VFS: fix aborting queued requests after FS crash
The new asserts from git-29e004d exposed an issue in how VFS handles
aborting file system (FS) requests that are queued for a FS (as
opposed to sent to it) when that FS crashes.  In that scenario, the
queued worker has its w_task set to NONE, because there is no ongoing
communication.  However, worker_stop() is called on it regardless,
which used to abort the request only if w_task was not set to NONE,
leading to an improperly aborted request, a warning, and a VFS crash a
bit later.  This patch changes worker_stop() so that w_task need not
be set to a valid endpoint for FS requests to be properly aborted.

Change-Id: Ib73db285e689ae4742b15cba26137bf340bc303b
2016-06-17 18:02:29 +00:00
9190 changed files with 2723253 additions and 124434 deletions

12
.gitignore vendored
View File

@@ -15,8 +15,10 @@ lib*.so*
*.a
*.so.*
*.d
!etc/*.d
.depend
nbsdsrc/*
*.gcno
*.gcda
TAGS
tags
GPATH
@@ -25,10 +27,10 @@ GSYMS
GTAGS
\#*#
CVS
obj
!/.gitignore
.gitignore
.svn
minix-port.patch
*.worldstone.log
.worldstone*
usr.bin/mdocml/man/*.7
@@ -39,5 +41,11 @@ releasetools/image
releasetools/kernel
releasetools/revision
share/zoneinfo/builddir
external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thu
external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-v
external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return
external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-a
external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors
external/bsd/llvm/dist/llvm/test/Verifier/bitcast-address-space-through-constant-inttoptr-inside-gep-i
lib/libc/compat__*
.gdbinit

View File

@@ -2,10 +2,6 @@
.include <bsd.own.mk>
.if defined(__MINIX)
SUBDIR+= openssl .WAIT heimdal netpgp .WAIT libsaslc
.else
SUBDIR+= openssl .WAIT heimdal netpgp .WAIT openssh libsaslc
.endif # defined(__MINIX)
.include <bsd.subdir.mk>

View File

@@ -7,11 +7,7 @@ SUBDIR=mech
.if ${MKSHARE} != "no"
FILESDIR=/usr/share/examples/libsaslc
FILESOWN=root
.if !defined(__MINIX)
FILESGRP=wheel
.else
FILESGRP=operator
.endif # !defined(__MINIX)
FILESMODE=444
FILES= saslc.conf

View File

@@ -5,11 +5,7 @@
.if ${MKSHARE} != "no"
FILESDIR=/usr/share/examples/libsaslc/mech
FILESOWN=root
.if !defined(__MINIX)
FILESGRP=wheel
.else
FILESGRP=operator
.endif # !defined(__MINIX)
FILESMODE=444
FILES=

5
crypto/external/bsd/openssh/Makefile vendored Normal file
View File

@@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2009/06/07 22:38:44 christos Exp $
SUBDIR= lib .WAIT bin
.include <bsd.subdir.mk>

View File

@@ -0,0 +1,51 @@
# $NetBSD: Makefile.inc,v 1.9 2015/07/23 08:03:25 mrg Exp $
WARNS?= 4
.include <bsd.own.mk>
USE_FORT?= yes # network client/server
WITH_OPENSSL=1
SSHDIST?= ${NETBSDSRCDIR}/crypto/external/bsd/openssh/dist
CPPFLAGS+=-I${SSHDIST}
CPPFLAGS+=-DHAVE_DLOPEN
CPPFLAGS+=-DHAVE_HEADER_AD
CPPFLAGS+=-DHAVE_STDLIB_H
.if !defined(NOPIC)
CPPFLAGS+=-DHAVE_DLOPEN
.endif
.PATH: ${SSHDIST}
.if (${USE_PAM} != "no")
CPPFLAGS+=-DUSE_PAM
.else # USE_PAM == no
.if (${USE_SKEY} != "no")
CPPFLAGS+=-DSKEY
.endif
.endif # USE_PAM == no
.if (${USE_KERBEROS} != "no")
CPPFLAGS+=-DGSSAPI
CPPFLAGS+=-DKRB5 -DHEIMDAL
.endif
.if (${USE_LDAP} != "no")
CPPFLAGS+=-DWITH_LDAP_PUBKEY
.endif
CPPFLAGS+=-DX11BASE=\"/usr/X11R7\"
CPPFLAGS+=-DSUPPORT_UTMP -DSUPPORT_UTMPX
.if defined(__MINIX)
CPPFLAGS+=-DWITH_SSH1 -DWITH_OPENSSL -D_OPENBSD_SOURCE
CPPFLAGS+=-g -O2 -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -ftrapv -fno-builtin-memset -Wno-error
CPPFLAGS+=-I. -I$(srcdir) $(PATHS) -DHAVE_CONFIG_H
.else
CPPFLAGS+=-DWITH_SSH1 -DWITH_OPENSSL -DENABLE_PKCS11 -D_OPENBSD_SOURCE
CPPFLAGS+=-DHAVE_LOGIN_CAP
CPPFLAGS+=-DLIBWRAP
.endif

View File

@@ -0,0 +1,17 @@
# $NetBSD: Makefile,v 1.3 2010/11/21 19:19:21 adam Exp $
.include <bsd.own.mk>
SSHDIST?= ${NETBSDSRCDIR}/crypto/external/bsd/openssh/dist
SUBDIR= ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server \
ssh-keysign ssh-keyscan sftp ssh-pkcs11-helper
.PATH: ${SSHDIST}
.MADE: moduli
CONFIGFILES= ssh_config sshd_config moduli
FILESDIR= /etc/ssh
FILESDIR_moduli=/etc
.include <bsd.files.mk>
.include <bsd.subdir.mk>

View File

@@ -0,0 +1,7 @@
# $NetBSD: Makefile.inc,v 1.3 2014/10/19 16:30:58 christos Exp $
CPPFLAGS+=-DWITH_OPENSSL
LDADD+= -lssh -lcrypto -lcrypt -lz
DPADD+= ${LIBSSH} ${LIBCRYPTO} ${LIBCRYPT} ${LIBZ}
.include "${.PARSEDIR}/../Makefile.inc"

View File

@@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2009/06/07 22:38:45 christos Exp $
BINDIR=/usr/bin
PROG= scp
SRCS= scp.c
.include <bsd.prog.mk>

View File

@@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.1 2009/06/07 22:38:45 christos Exp $
BINDIR= /usr/libexec
PROG= sftp-server
SRCS= sftp-server.c sftp-common.c sftp-server-main.c
MAN= sftp-server.8
.include <bsd.prog.mk>

View File

@@ -0,0 +1,15 @@
# $NetBSD: Makefile,v 1.5 2012/08/10 12:20:11 joerg Exp $
BINDIR= /usr/bin
PROG= sftp
SRCS= sftp.c sftp-client.c sftp-common.c sftp-glob.c
MAN= sftp.1
LDADD+= -ledit -lterminfo
DPADD+= ${LIBEDIT} ${LIBTERMINFO}
COPTS.sftp.c+= -Wno-pointer-sign
COPTS.sftp-client.c+= -Wno-pointer-sign
.include <bsd.prog.mk>

View File

@@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2009/06/07 22:38:45 christos Exp $
BINDIR=/usr/bin
PROG= ssh-add
SRCS= ssh-add.c
.include <bsd.prog.mk>

View File

@@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.2 2010/11/21 19:19:22 adam Exp $
BINDIR=/usr/bin
PROG= ssh-agent
SRCS= ssh-agent.c ssh-pkcs11-client.c
.include <bsd.prog.mk>

View File

@@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.4 2012/08/10 12:20:12 joerg Exp $
BINDIR= /usr/bin
PROG= ssh-keygen
SRCS= ssh-keygen.c moduli.c
COPTS.ssh-keygen.c= -Wno-pointer-sign
.include <bsd.prog.mk>

View File

@@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.2 2015/04/03 23:58:19 christos Exp $
BINDIR= /usr/bin
PROG= ssh-keyscan
SRCS= ssh-keyscan.c ssh_api.c kexdhs.c kexgexs.c kexecdhs.c
MAN= ssh-keyscan.1
.include <bsd.prog.mk>

View File

@@ -0,0 +1,11 @@
# $NetBSD: Makefile,v 1.1 2009/06/07 22:38:46 christos Exp $
BINOWN= root
BINMODE=4555
BINDIR= /usr/libexec
PROG= ssh-keysign
SRCS= ssh-keysign.c readconf.c
MAN= ssh-keysign.8
.include <bsd.prog.mk>

View File

@@ -0,0 +1,11 @@
# $NetBSD: Makefile,v 1.1 2010/11/21 19:19:22 adam Exp $
BINOWN= root
BINMODE=555
BINDIR= /usr/libexec
PROG= ssh-pkcs11-helper
SRCS= ssh-pkcs11-helper.c
MAN= ssh-pkcs11-helper.8
.include <bsd.prog.mk>

View File

@@ -0,0 +1,36 @@
# $NetBSD: Makefile,v 1.8 2012/08/10 12:20:12 joerg Exp $
.include <bsd.own.mk>
BINDIR = /usr/bin
PROG= ssh
SRCS= ssh.c readconf.c clientloop.c sshtty.c \
sshconnect.c sshconnect1.c sshconnect2.c mux.c \
roaming_common.c roaming_client.c
COPTS.sshconnect1.c= -fno-strict-aliasing
COPTS.mux.c= -Wno-pointer-sign
COPTS.sshconnect2.c= -Wno-pointer-sign
LINKS= ${BINDIR}/ssh ${BINDIR}/slogin
MAN= ssh.1 ssh_config.5
MLINKS= ssh.1 slogin.1
.if (${USE_KERBEROS} != "no")
# this is not entirely true, libgssapi might be independent of krb5
SRCS += gss-genr.c
LDADD+= -lgssapi -lheimntlm
DPADD+= ${LIBGSSAPI} ${LIBHEIMNTLM}
LDADD+= -lkrb5 -lhx509 -lheimbase -lwind
DPADD+= ${LIBKRB5} ${LIBHX509} ${LIBHEIMBASE} ${LIBWIND}
LDADD+= -lkafs -lasn1 -lcrypt
DPADD+= ${LIBKAFS} ${LIBASN1} ${LIBCRYPT}
LDADD+= -lcom_err -lroken -lutil
DPADD+= ${LIBCOM_ERR} ${LIBROKEN} ${LIBUTIL}
.endif
.include <bsd.prog.mk>

View File

@@ -0,0 +1,100 @@
# $NetBSD: Makefile,v 1.12 2015/01/26 03:57:17 christos Exp $
.include <bsd.own.mk>
PROG= sshd
MAN= sshd.8 sshd_config.5 moduli.5
BINDIR= /usr/sbin
.if defined(__MINIX)
SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \
audit.c audit-bsm.c audit-linux.c platform.c \
sshpty.c sshlogin.c servconf.c serverloop.c \
auth.c auth1.c auth2.c auth-options.c session.c \
auth-chall.c auth2-chall.c groupaccess.c \
auth-skey.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c \
auth2-none.c auth2-passwd.c auth2-pubkey.c \
monitor_mm.c monitor.c monitor_wrap.c auth-krb5.c \
auth2-gss.c gss-serv.c gss-serv-krb5.c \
loginrec.c auth-pam.c auth-shadow.c auth-sia.c md5crypt.c \
sftp-server.c sftp-common.c \
roaming_common.c roaming_serv.c \
sandbox-null.c sandbox-rlimit.c sandbox-systrace.c sandbox-darwin.c \
sandbox-seccomp-filter.c sandbox-capsicum.c
.else
SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \
sshpty.c sshlogin.c servconf.c serverloop.c \
auth.c auth1.c auth2.c auth-options.c session.c \
auth-chall.c auth2-chall.c groupaccess.c \
auth-skey.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c \
auth2-none.c auth2-passwd.c auth2-pubkey.c \
monitor_mm.c monitor.c monitor_wrap.c \
kexdhs.c kexgexs.c kexecdhs.c sftp-server.c sftp-common.c \
roaming_common.c roaming_serv.c sandbox-rlimit.c pfilter.c
.endif
COPTS.auth-options.c= -Wno-pointer-sign
COPTS.ldapauth.c= -Wno-format-nonliteral # XXX: should fix
.if (${USE_PAM} != "no")
SRCS+= auth-pam.c
LDADD+= -lpam ${PAM_STATIC_LDADD}
DPADD+= ${LIBPAM} ${PAM_STATIC_DPADD}
.if ${USE_YP} != "no"
LDADD+= -lrpcsvc
DPADD+= ${LIBRPCSVC}
.endif
.else # USE_PAM == no
.if (${USE_SKEY} != "no")
LDADD+= -lskey
DPADD+= ${LIBSKEY}
.endif
.endif # USE_PAM == no
.if (${USE_KERBEROS} != "no")
SRCS+= gss-genr.c auth2-gss.c gss-serv.c gss-serv-krb5.c
LDADD+= -lgssapi -lheimntlm
DPADD+= ${LIBGSSAPI} ${LIBHEIMNTLM}
LDADD+= -lkafs
DPADD+= ${LIBKAFS}
SRCS+= auth-krb5.c auth2-krb5.c
LDADD+= -lkrb5 -lasn1
DPADD+= ${LIBKRB5} ${LIBASN1}
LDADD+= -lcom_err -lroken
DPADD+= ${LIBCOM_ERR} ${LIBROKEN}
.endif
.if (${USE_LDAP} != "no")
SRCS+= ldapauth.c
LDADD+= -lldap -lssl -llber
DPADD+= ${LIBLDAP} ${LIBSSL} ${LIBLBER}
.endif
.include <bsd.prog.mk>
LDADD+= -lcrypt -lutil
DPADD+= ${LIBCRYPT} ${LIBUTIL}
.if defined(__MINIX)
LDADD+=
DPADD+=
.else
LDADD+= -lwrap
DPADD+= ${LIBWRAP}
.ifdef CRUNCHEDPROG
CPPFLAGS+=-DSMALL
.else
LDADD+= -lblacklist
DPADD+= ${LIBBLACKLIST}
.endif
.endif

105
crypto/external/bsd/openssh/dist/CREDITS vendored Normal file
View File

@@ -0,0 +1,105 @@
Tatu Ylonen <ylo@cs.hut.fi> - Creator of SSH
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
Theo de Raadt, and Dug Song - Creators of OpenSSH
Ahsan Rashid <arms@sco.com> - UnixWare long passwords
Alain St-Denis <Alain.St-Denis@ec.gc.ca> - Irix fix
Alexandre Oliva <oliva@lsd.ic.unicamp.br> - AIX fixes
Andre Lucas <andre@ae-35.com> - new login code, many fixes
Andreas Steinmetz <ast@domdv.de> - Shadow password expiry support
Andrew McGill <andrewm@datrix.co.za> - SCO fixes
Andrew Morgan <morgan@transmeta.com> - PAM bugfixes
Andrew Stribblehill <a.d.stribblehill@durham.ac.uk> - Bugfixes
Andy Sloane <andy@guildsoftware.com> - bugfixes
Aran Cox <acox@cv.telegroup.com> - SCO bugfixes
Arkadiusz Miskiewicz <misiek@pld.org.pl> - IPv6 compat fixes
Ben Lindstrom <mouring@eviladmin.org> - NeXT support
Ben Taylor <bent@clark.net> - Solaris debugging and fixes
Bratislav ILICH <bilic@zepter.ru> - Configure fix
Charles Levert <charles@comm.polymtl.ca> - SunOS 4 & bug fixes
Chip Salzenberg <chip@valinux.com> - Assorted patches
Chris Adams <cmadams@hiwaay.net> - OSF SIA support
Chris Saia <csaia@wtower.com> - SuSE packaging
Chris, the Young One <cky@pobox.com> - Password auth fixes
Christos Zoulas <christos@zoulas.com> - Autoconf fixes
Chun-Chung Chen <cjj@u.washington.edu> - RPM fixes
Corinna Vinschen <vinschen@redhat.com> - Cygwin support
Chad Mynhier <mynhier@interstel.net> - Solaris Process Contract support
Dan Brosemer <odin@linuxfreak.com> - Autoconf support, build fixes
Darren Hall <dhall@virage.org> - AIX patches
Darren Tucker <dtucker@zip.com.au> - AIX BFF package scripts
David Agraz <dagraz@jahoopa.com> - Build fixes
David Del Piero <David.DelPiero@qed.qld.gov.au> - bug fixes
David Hesprich <darkgrue@gue-tech.org> - Configure fixes
David Rankin <drankin@bohemians.lexington.ky.us> - libwrap, AIX, NetBSD fixes
Dag-Erling Smørgrav <des at freebsd.org> - Challenge-Response PAM code.
Dhiraj Gulati <dgulati@sco.com> - UnixWare long passwords
Ed Eden <ede370@stl.rural.usda.gov> - configure fixes
Garrick James <garrick@james.net> - configure fixes
Gary E. Miller <gem@rellim.com> - SCO support
Ged Lodder <lodder@yacc.com.au> - HPUX fixes and enhancements
Gert Doering <gd@hilb1.medat.de> - bug and portability fixes
HARUYAMA Seigo <haruyama@unixuser.org> - Translations & doc fixes
Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp> - IPv6 and bug fixes
Hiroshi Takekawa <takekawa@sr3.t.u-tokyo.ac.jp> - Configure fixes
Holger Trapp <Holger.Trapp@Informatik.TU-Chemnitz.DE> - KRB4/AFS config patch
IWAMURO Motonori <iwa@mmp.fujitsu.co.jp> - bugfixes
Jani Hakala <jahakala@cc.jyu.fi> - Patches
Jarno Huuskonen <jhuuskon@hytti.uku.fi> - Bugfixes
Jim Knoble <jmknoble@pobox.com> - Many patches
Jonchen (email unknown) - the original author of PAM support of SSH
Juergen Keil <jk@tools.de> - scp bugfixing
KAMAHARA Junzo <kamahara@cc.kshosen.ac.jp> - Configure fixes
Kees Cook <cook@cpoint.net> - scp fixes
Kenji Miyake <kenji@miyake.org> - Configure fixes
Kevin Cawlfield <cawlfiel@us.ibm.com> - AIX fixes.
Kevin O'Connor <kevin_oconnor@standardandpoors.com> - RSAless operation
Kevin Steves <stevesk@pobox.com> - HP support, bugfixes, improvements
Kiyokazu SUTO <suto@ks-and-ks.ne.jp> - Bugfixes
Larry Jones <larry.jones@sdrc.com> - Bugfixes
Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> - Bugfixes
Marc G. Fournier <marc.fournier@acadiau.ca> - Solaris patches
Mark D. Baushke <mdb@juniper.net> - bug fixes
Martin Johansson <fatbob@acc.umu.se> - Linux fixes
Mark D. Roth <roth+openssh@feep.net> - Features, bug fixes
Mark Miller <markm@swoon.net> - Bugfixes
Matt Richards <v2matt@btv.ibm.com> - AIX patches
Michael Steffens <michael_steffens at hp.com> - HP-UX fixes
Michael Stone <mstone@cs.loyola.edu> - Irix enhancements
Nakaji Hiroyuki <nakaji@tutrp.tut.ac.jp> - Sony News-OS patch
Nalin Dahyabhai <nalin.dahyabhai@pobox.com> - PAM environment patch
Nate Itkin <nitkin@europa.com> - SunOS 4.1.x fixes
Niels Kristian Bech Jensen <nkbj@image.dk> - Assorted patches
Pavel Kankovsky <peak@argo.troja.mff.cuni.cz> - Security fixes
Pavel Troller <patrol@omni.sinus.cz> - Bugfixes
Pekka Savola <pekkas@netcore.fi> - Bugfixes
Peter Kocks <peter.kocks@baygate.com> - Makefile fixes
Peter Stuge <stuge@cdy.org> - mdoc2man.awk script
Phil Hands <phil@hands.com> - Debian scripts, assorted patches
Phil Karn <karn@ka9q.ampr.org> - Autoconf fixes
Philippe WILLEM <Philippe.WILLEM@urssaf.fr> - Bugfixes
Phill Camp <P.S.S.Camp@ukc.ac.uk> - login code fix
Rip Loomis <loomisg@cist.saic.com> - Solaris package support, fixes
Robert Dahlem <Robert.Dahlem at siemens.com> - Reliant Unix fixes
Roumen Petrov <openssh@roumenpetrov.info> - Compile & configure fixes
SAKAI Kiyotaka <ksakai@kso.netwk.ntt-at.co.jp> - Multiple bugfixes
Simon Wilkinson <sxw@dcs.ed.ac.uk> - PAM fixes, Compat with MIT KrbV
Solar Designer <solar@openwall.com> - many patches and technical assistance
Svante Signell <svante.signell@telia.com> - Bugfixes
Thomas Neumann <tom@smart.ruhr.de> - Shadow passwords
Tim Rice <tim@multitalents.net> - Portability & SCO fixes
Tobias Oetiker <oetiker@ee.ethz.ch> - Bugfixes
Tom Bertelson's <tbert@abac.com> - AIX auth fixes
Tor-Ake Fransson <torake@hotmail.com> - AIX support
Tudor Bosman <tudorb@jm.nu> - MD5 password support
Udo Schweigert <ust@cert.siemens.de> - ReliantUNIX support
Wendy Palm <wendyp at cray.com> - Cray support.
Zack Weinberg <zack@wolery.cumb.org> - GNOME askpass enhancement
Apologies to anyone I have missed.
Damien Miller <djm@mindrot.org>
$Id: CREDITS,v 1.81 2006/08/30 17:24:41 djm Exp $

9133
crypto/external/bsd/openssh/dist/ChangeLog vendored Normal file

File diff suppressed because it is too large Load Diff

262
crypto/external/bsd/openssh/dist/INSTALL vendored Normal file
View File

@@ -0,0 +1,262 @@
1. Prerequisites
----------------
You will need working installations of Zlib and libcrypto (LibreSSL /
OpenSSL)
Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems):
http://www.gzip.org/zlib/
libcrypto (LibreSSL or OpenSSL >= 0.9.8f)
LibreSSL http://www.libressl.org/ ; or
OpenSSL http://www.openssl.org/
LibreSSL/OpenSSL should be compiled as a position-independent library
(i.e. with -fPIC) otherwise OpenSSH will not be able to link with it.
If you must use a non-position-independent libcrypto, then you may need
to configure OpenSSH --without-pie.
The remaining items are optional.
NB. If you operating system supports /dev/random, you should configure
libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's
direct support of /dev/random, or failing that, either prngd or egd
PRNGD:
If your system lacks kernel-based random collection, the use of Lutz
Jaenicke's PRNGd is recommended.
http://prngd.sourceforge.net/
EGD:
If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is
supported only if libcrypto supports it.
http://egd.sourceforge.net/
PAM:
OpenSSH can utilise Pluggable Authentication Modules (PAM) if your
system supports it. PAM is standard most Linux distributions, Solaris,
HP-UX 11, AIX >= 5.2, FreeBSD and NetBSD.
Information about the various PAM implementations are available:
Solaris PAM: http://www.sun.com/software/solaris/pam/
Linux PAM: http://www.kernel.org/pub/linux/libs/pam/
OpenPAM: http://www.openpam.org/
If you wish to build the GNOME passphrase requester, you will need the GNOME
libraries and headers.
GNOME:
http://www.gnome.org/
Alternatively, Jim Knoble <jmknoble@pobox.com> has written an excellent X11
passphrase requester. This is maintained separately at:
http://www.jmknoble.net/software/x11-ssh-askpass/
S/Key Libraries:
If you wish to use --with-skey then you will need the library below
installed. No other S/Key library is currently known to be supported.
http://www.sparc.spb.su/solaris/skey/
LibEdit:
sftp supports command-line editing via NetBSD's libedit. If your platform
has it available natively you can use that, alternatively you might try
these multi-platform ports:
http://www.thrysoee.dk/editline/
http://sourceforge.net/projects/libedit/
LDNS:
LDNS is a DNS BSD-licensed resolver library which supports DNSSEC.
http://nlnetlabs.nl/projects/ldns/
Autoconf:
If you modify configure.ac or configure doesn't exist (eg if you checked
the code out of CVS yourself) then you will need autoconf-2.68 to rebuild
the automatically generated files by running "autoreconf". Earlier
versions may also work but this is not guaranteed.
http://www.gnu.org/software/autoconf/
Basic Security Module (BSM):
Native BSM support is know to exist in Solaris from at least 2.5.1,
FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM
implementation (http://www.openbsm.org).
2. Building / Installation
--------------------------
To install OpenSSH with default options:
./configure
make
make install
This will install the OpenSSH binaries in /usr/local/bin, configuration files
in /usr/local/etc, the server in /usr/local/sbin, etc. To specify a different
installation prefix, use the --prefix option to configure:
./configure --prefix=/opt
make
make install
Will install OpenSSH in /opt/{bin,etc,lib,sbin}. You can also override
specific paths, for example:
./configure --prefix=/opt --sysconfdir=/etc/ssh
make
make install
This will install the binaries in /opt/{bin,lib,sbin}, but will place the
configuration files in /etc/ssh.
If you are using Privilege Separation (which is enabled by default)
then you will also need to create the user, group and directory used by
sshd for privilege separation. See README.privsep for details.
If you are using PAM, you may need to manually install a PAM control
file as "/etc/pam.d/sshd" (or wherever your system prefers to keep
them). Note that the service name used to start PAM is __progname,
which is the basename of the path of your sshd (e.g., the service name
for /usr/sbin/osshd will be osshd). If you have renamed your sshd
executable, your PAM configuration may need to be modified.
A generic PAM configuration is included as "contrib/sshd.pam.generic",
you may need to edit it before using it on your system. If you are
using a recent version of Red Hat Linux, the config file in
contrib/redhat/sshd.pam should be more useful. Failure to install a
valid PAM file may result in an inability to use password
authentication. On HP-UX 11 and Solaris, the standard /etc/pam.conf
configuration will work with sshd (sshd will match the other service
name).
There are a few other options to the configure script:
--with-audit=[module] enable additional auditing via the specified module.
Currently, drivers for "debug" (additional info via syslog) and "bsm"
(Sun's Basic Security Module) are supported.
--with-pam enables PAM support. If PAM support is compiled in, it must
also be enabled in sshd_config (refer to the UsePAM directive).
--with-prngd-socket=/some/file allows you to enable EGD or PRNGD
support and to specify a PRNGd socket. Use this if your Unix lacks
/dev/random and you don't want to use OpenSSH's builtin entropy
collection support.
--with-prngd-port=portnum allows you to enable EGD or PRNGD support
and to specify a EGD localhost TCP port. Use this if your Unix lacks
/dev/random and you don't want to use OpenSSH's builtin entropy
collection support.
--with-lastlog=FILE will specify the location of the lastlog file.
./configure searches a few locations for lastlog, but may not find
it if lastlog is installed in a different place.
--without-lastlog will disable lastlog support entirely.
--with-osfsia, --without-osfsia will enable or disable OSF1's Security
Integration Architecture. The default for OSF1 machines is enable.
--with-skey=PATH will enable S/Key one time password support. You will
need the S/Key libraries and header files installed for this to work.
--with-md5-passwords will enable the use of MD5 passwords. Enable this
if your operating system uses MD5 passwords and the system crypt() does
not support them directly (see the crypt(3/3c) man page). If enabled, the
resulting binary will support both MD5 and traditional crypt passwords.
--with-utmpx enables utmpx support. utmpx support is automatic for
some platforms.
--without-shadow disables shadow password support.
--with-ipaddr-display forces the use of a numeric IP address in the
$DISPLAY environment variable. Some broken systems need this.
--with-default-path=PATH allows you to specify a default $PATH for sessions
started by sshd. This replaces the standard path entirely.
--with-pid-dir=PATH specifies the directory in which the sshd.pid file is
created.
--with-xauth=PATH specifies the location of the xauth binary
--with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL
libraries
are installed.
--with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
If you need to pass special options to the compiler or linker, you
can specify these as environment variables before running ./configure.
For example:
CFLAGS="-O -m486" LDFLAGS="-s" LIBS="-lrubbish" LD="/usr/foo/ld" ./configure
3. Configuration
----------------
The runtime configuration files are installed by in ${prefix}/etc or
whatever you specified as your --sysconfdir (/usr/local/etc by default).
The default configuration should be instantly usable, though you should
review it to ensure that it matches your security requirements.
To generate a host key, run "make host-key". Alternately you can do so
manually using the following commands:
ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N ""
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ""
ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ""
Replacing /etc/ssh with the correct path to the configuration directory.
(${prefix}/etc or whatever you specified with --sysconfdir during
configuration)
If you have configured OpenSSH with EGD support, ensure that EGD is
running and has collected some Entropy.
For more information on configuration, please refer to the manual pages
for sshd, ssh and ssh-agent.
4. (Optional) Send survey
-------------------------
$ make survey
[check the contents of the file "survey" to ensure there's no information
that you consider sensitive]
$ make send-survey
This will send configuration information for the currently configured
host to a survey address. This will help determine which configurations
are actually in use, and what valid combinations of configure options
exist. The raw data is available only to the OpenSSH developers, however
summary data may be published.
5. Problems?
------------
If you experience problems compiling, installing or running OpenSSH.
Please refer to the "reporting bugs" section of the webpage at
http://www.openssh.com/
$Id: INSTALL,v 1.91 2014/09/09 02:23:11 dtucker Exp $

340
crypto/external/bsd/openssh/dist/LICENCE vendored Normal file
View File

@@ -0,0 +1,340 @@
This file is part of the OpenSSH software.
The licences which components of this software fall under are as
follows. First, we will summarize and say that all components
are under a BSD licence, or a licence more free than that.
OpenSSH contains no GPL code.
1)
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* 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".
[Tatu continues]
* However, I am not implying to give any licenses to any patents or
* copyrights held by third parties, and the software includes parts that
* are not under my direct control. As far as I know, all included
* source code is used in accordance with the relevant license agreements
* and can be used freely for any purpose (the GNU license being the most
* restrictive); see below for details.
[However, none of that term is relevant at this point in time. All of
these restrictively licenced software components which he talks about
have been removed from OpenSSH, i.e.,
- RSA is no longer included, found in the OpenSSL library
- IDEA is no longer included, its use is deprecated
- DES is now external, in the OpenSSL library
- GMP is no longer used, and instead we call BN code from OpenSSL
- Zlib is now external, in a library
- The make-ssh-known-hosts script is no longer included
- TSS has been removed
- MD5 is now external, in the OpenSSL library
- RC4 support has been replaced with ARC4 support from OpenSSL
- Blowfish is now external, in the OpenSSL library
[The licence continues]
Note that any information and cryptographic algorithms used in this
software are publicly available on the Internet and at any major
bookstore, scientific library, and patent office worldwide. More
information can be found e.g. at "http://www.cs.hut.fi/crypto".
The legal status of this program is some combination of all these
permissions and restrictions. Use only at your own responsibility.
You will be responsible for any legal consequences yourself; I am not
making any claims whether possessing or using this is legal or not in
your country, and I am not taking any responsibility on your behalf.
NO WARRANTY
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
2)
The 32-bit CRC compensation attack detector in deattack.c was
contributed by CORE SDI S.A. under a BSD-style license.
* Cryptographic attack detector for ssh - source code
*
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
*
* All rights reserved. Redistribution and use in source and binary
* forms, with or without modification, are permitted provided that
* this copyright notice is retained.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
* CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
* SOFTWARE.
*
* Ariel Futoransky <futo@core-sdi.com>
* <http://www.core-sdi.com>
3)
ssh-keyscan was contributed by David Mazieres under a BSD-style
license.
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
* Modification and redistribution in source and binary forms is
* permitted provided that due credit is given to the author and the
* OpenBSD project by leaving this copyright notice intact.
4)
The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers
and Paulo Barreto is in the public domain and distributed
with the following license:
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5)
One component of the ssh source code is under a 3-clause BSD license,
held by the University of California, since we pulled these parts from
original Berkeley code.
* Copyright (c) 1983, 1990, 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
6)
Remaining components of the software are provided under a standard
2-term BSD licence with the following names as copyright holders:
Markus Friedl
Theo de Raadt
Niels Provos
Dug Song
Aaron Campbell
Damien Miller
Kevin Steves
Daniel Kouril
Wesley Griffin
Per Allansson
Nils Nordman
Simon Wilkinson
Portable OpenSSH additionally includes code from the following copyright
holders, also under the 2-term BSD license:
Ben Lindstrom
Tim Rice
Andre Lucas
Chris Adams
Corinna Vinschen
Cray Inc.
Denis Parker
Gert Doering
Jakob Schlyter
Jason Downs
Juha Yrjölä
Michael Stone
Networks Associates Technology, Inc.
Solar Designer
Todd C. Miller
Wayne Schroeder
William Jones
Darren Tucker
Sun Microsystems
The SCO Group
Daniel Walsh
Red Hat, Inc
Simon Vallet / Genoscope
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8) Portable OpenSSH contains the following additional licenses:
a) md5crypt.c, md5crypt.h
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> wrote this file. As long as you retain this
* notice you can do whatever you want with this stuff. If we meet
* some day, and you think this stuff is worth it, you can buy me a
* beer in return. Poul-Henning Kamp
b) snprintf replacement
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell
* (papowell@astart.com) It may be used for any purpose as long as this
* notice remains intact on all source code distributions
c) Compatibility code (openbsd-compat)
Apart from the previously mentioned licenses, various pieces of code
in the openbsd-compat/ subdirectory are licensed as follows:
Some code is licensed under a 3-term BSD license, to the following
copyright holders:
Todd C. Miller
Theo de Raadt
Damien Miller
Eric P. Allman
The Regents of the University of California
Constantin S. Svintsoff
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
Some code is licensed under an ISC-style license, to the following
copyright holders:
Internet Software Consortium.
Todd C. Miller
Reyk Floeter
Chad Mynhier
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Some code is licensed under a MIT-style license to the following
copyright holders:
Free Software Foundation, Inc.
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
* "Software"), to deal in the Software without restriction, including *
* without limitation the rights to use, copy, modify, merge, publish, *
* distribute, distribute with modifications, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included *
* in all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
* *
* Except as contained in this notice, the name(s) of the above copyright *
* holders shall not be used in advertising or otherwise to promote the *
* sale, use or other dealings in this Software without prior written *
* authorization. *
****************************************************************************/
------
$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $

View File

@@ -0,0 +1,168 @@
[Note: This file has not been updated for OpenSSH versions after
OpenSSH-1.2 and should be considered OBSOLETE. It has been left in
the distribution because some of its information may still be useful
to developers.]
This document is intended for those who wish to read the ssh source
code. This tries to give an overview of the structure of the code.
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
Updated 17 Nov 1995.
Updated 19 Oct 1999 for OpenSSH-1.2
Updated 20 May 2001 note obsolete for > OpenSSH-1.2
The software consists of ssh (client), sshd (server), scp, sdist, and
the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and
make-ssh-known-hosts. The main program for each of these is in a .c
file with the same name.
There are some subsystems/abstractions that are used by a number of
these programs.
Buffer manipulation routines
- These provide an arbitrary size buffer, where data can be appended.
Data can be consumed from either end. The code is used heavily
throughout ssh. The basic buffer manipulation functions are in
buffer.c (header buffer.h), and additional code to manipulate specific
data types is in bufaux.c.
Compression Library
- Ssh uses the GNU GZIP compression library (ZLIB).
Encryption/Decryption
- Ssh contains several encryption algorithms. These are all
accessed through the cipher.h interface. The interface code is
in cipher.c, and the implementations are in libc.
Multiple Precision Integer Library
- Uses the SSLeay BIGNUM sublibrary.
Random Numbers
- Uses arc4random() and such.
RSA key generation, encryption, decryption
- Ssh uses the RSA routines in libssl.
RSA key files
- RSA keys are stored in files with a special format. The code to
read/write these files is in authfile.c. The files are normally
encrypted with a passphrase. The functions to read passphrases
are in readpass.c (the same code is used to read passwords).
Binary packet protocol
- The ssh binary packet protocol is implemented in packet.c. The
code in packet.c does not concern itself with packet types or their
execution; it contains code to build packets, to receive them and
extract data from them, and the code to compress and/or encrypt
packets. CRC code comes from crc32.c.
- The code in packet.c calls the buffer manipulation routines
(buffer.c, bufaux.c), compression routines (zlib), and the
encryption routines.
X11, TCP/IP, and Agent forwarding
- Code for various types of channel forwarding is in channels.c.
The file defines a generic framework for arbitrary communication
channels inside the secure channel, and uses this framework to
implement X11 forwarding, TCP/IP forwarding, and authentication
agent forwarding.
The new, Protocol 1.5, channel close implementation is in nchan.c
Authentication agent
- Code to communicate with the authentication agent is in authfd.c.
Authentication methods
- Code for various authentication methods resides in auth-*.c
(auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This
code is linked into the server. The routines also manipulate
known hosts files using code in hostfile.c. Code in canohost.c
is used to retrieve the canonical host name of the remote host.
Code in match.c is used to match host names.
- In the client end, authentication code is in sshconnect.c. It
reads Passwords/passphrases using code in readpass.c. It reads
RSA key files with authfile.c. It communicates the
authentication agent using authfd.c.
The ssh client
- The client main program is in ssh.c. It first parses arguments
and reads configuration (readconf.c), then calls ssh_connect (in
sshconnect.c) to open a connection to the server (possibly via a
proxy), and performs authentication (ssh_login in sshconnect.c).
It then makes any pty, forwarding, etc. requests. It may call
code in ttymodes.c to encode current tty modes. Finally it
calls client_loop in clientloop.c. This does the real work for
the session.
- The client is suid root. It tries to temporarily give up this
rights while reading the configuration data. The root
privileges are only used to make the connection (from a
privileged socket). Any extra privileges are dropped before
calling ssh_login.
Pseudo-tty manipulation and tty modes
- Code to allocate and use a pseudo tty is in pty.c. Code to
encode and set terminal modes is in ttymodes.c.
Logging in (updating utmp, lastlog, etc.)
- The code to do things that are done when a user logs in are in
login.c. This includes things such as updating the utmp, wtmp,
and lastlog files. Some of the code is in sshd.c.
Writing to the system log and terminal
- The programs use the functions fatal(), log(), debug(), error()
in many places to write messages to system log or user's
terminal. The implementation that logs to system log is in
log-server.c; it is used in the server program. The other
programs use an implementation that sends output to stderr; it
is in log-client.c. The definitions are in ssh.h.
The sshd server (daemon)
- The sshd daemon starts by processing arguments and reading the
configuration file (servconf.c). It then reads the host key,
starts listening for connections, and generates the server key.
The server key will be regenerated every hour by an alarm.
- When the server receives a connection, it forks, disables the
regeneration alarm, and starts communicating with the client.
They first perform identification string exchange, then
negotiate encryption, then perform authentication, preparatory
operations, and finally the server enters the normal session
mode by calling server_loop in serverloop.c. This does the real
work, calling functions in other modules.
- The code for the server is in sshd.c. It contains a lot of
stuff, including:
- server main program
- waiting for connections
- processing new connection
- authentication
- preparatory operations
- building up the execution environment for the user program
- starting the user program.
Auxiliary files
- There are several other files in the distribution that contain
various auxiliary routines:
ssh.h the main header file for ssh (various definitions)
uidswap.c uid-swapping
xmalloc.c "safe" malloc routines
$OpenBSD: OVERVIEW,v 1.12 2015/07/08 19:01:15 markus Exp $

View File

@@ -0,0 +1,455 @@
This documents OpenSSH's deviations and extensions to the published SSH
protocol.
Note that OpenSSH's sftp and sftp-server implement revision 3 of the SSH
filexfer protocol described in:
http://www.openssh.com/txt/draft-ietf-secsh-filexfer-02.txt
Newer versions of the draft will not be supported, though some features
are individually implemented as extensions described below.
The protocol used by OpenSSH's ssh-agent is described in the file
PROTOCOL.agent
1. Transport protocol changes
1.1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com"
This is a new transport-layer MAC method using the UMAC algorithm
(rfc4418). This method is identical to the "umac-64" method documented
in:
http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt
1.2. transport: Protocol 2 compression algorithm "zlib@openssh.com"
This transport-layer compression method uses the zlib compression
algorithm (identical to the "zlib" method in rfc4253), but delays the
start of compression until after authentication has completed. This
avoids exposing compression code to attacks from unauthenticated users.
The method is documented in:
http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com",
"ssh-dsa-cert-v00@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com" and
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
OpenSSH introduces new public key algorithms to support certificate
authentication for users and host keys. These methods are documented
in the file PROTOCOL.certkeys
1.4. transport: Elliptic Curve cryptography
OpenSSH supports ECC key exchange and public key authentication as
specified in RFC5656. Only the ecdsa-sha2-nistp256, ecdsa-sha2-nistp384
and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
curve points encoded using point compression are NOT accepted or
generated.
1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms
OpenSSH supports MAC algorithms, whose names contain "-etm", that
perform the calculations in a different order to that defined in RFC
4253. These variants use the so-called "encrypt then MAC" ordering,
calculating the MAC over the packet ciphertext rather than the
plaintext. This ordering closes a security flaw in the SSH transport
protocol, where decryption of unauthenticated ciphertext provided a
"decryption oracle" that could, in conjunction with cipher flaws, reveal
session plaintext.
Specifically, the "-etm" MAC algorithms modify the transport protocol
to calculate the MAC over the packet ciphertext and to send the packet
length unencrypted. This is necessary for the transport to obtain the
length of the packet and location of the MAC tag so that it may be
verified without decrypting unauthenticated data.
As such, the MAC covers:
mac = MAC(key, sequence_number || packet_length || encrypted_packet)
where "packet_length" is encoded as a uint32 and "encrypted_packet"
contains:
byte padding_length
byte[n1] payload; n1 = packet_length - padding_length - 1
byte[n2] random padding; n2 = padding_length
1.6 transport: AES-GCM
OpenSSH supports the AES-GCM algorithm as specified in RFC 5647.
Because of problems with the specification of the key exchange
the behaviour of OpenSSH differs from the RFC as follows:
AES-GCM is only negotiated as the cipher algorithms
"aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as
an MAC algorithm. Additionally, if AES-GCM is selected as the cipher
the exchanged MAC algorithms are ignored and there doesn't have to be
a matching MAC.
1.7 transport: chacha20-poly1305@openssh.com authenticated encryption
OpenSSH supports authenticated encryption using ChaCha20 and Poly1305
as described in PROTOCOL.chacha20poly1305.
1.8 transport: curve25519-sha256@libssh.org key exchange algorithm
OpenSSH supports the use of ECDH in Curve25519 for key exchange as
described at:
http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519
2. Connection protocol changes
2.1. connection: Channel write close extension "eow@openssh.com"
The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF
message to allow an endpoint to signal its peer that it will send no
more data over a channel. Unfortunately, there is no symmetric way for
an endpoint to request that its peer should cease sending data to it
while still keeping the channel open for the endpoint to send data to
the peer.
This is desirable, since it saves the transmission of data that would
otherwise need to be discarded and it allows an endpoint to signal local
processes of the condition, e.g. by closing the corresponding file
descriptor.
OpenSSH implements a channel extension message to perform this
signalling: "eow@openssh.com" (End Of Write). This message is sent by
an endpoint when the local output of a session channel is closed or
experiences a write error. The message is formatted as follows:
byte SSH_MSG_CHANNEL_REQUEST
uint32 recipient channel
string "eow@openssh.com"
boolean FALSE
On receiving this message, the peer SHOULD cease sending data of
the channel and MAY signal the process from which the channel data
originates (e.g. by closing its read file descriptor).
As with the symmetric SSH_MSG_CHANNEL_EOF message, the channel does
remain open after a "eow@openssh.com" has been sent and more data may
still be sent in the other direction. This message does not consume
window space and may be sent even if no window space is available.
NB. due to certain broken SSH implementations aborting upon receipt
of this message (in contravention of RFC4254 section 5.4), this
message is only sent to OpenSSH peers (identified by banner).
Other SSH implementations may be whitelisted to receive this message
upon request.
2.2. connection: disallow additional sessions extension
"no-more-sessions@openssh.com"
Most SSH connections will only ever request a single session, but a
attacker may abuse a running ssh client to surreptitiously open
additional sessions under their control. OpenSSH provides a global
request "no-more-sessions@openssh.com" to mitigate this attack.
When an OpenSSH client expects that it will never open another session
(i.e. it has been started with connection multiplexing disabled), it
will send the following global request:
byte SSH_MSG_GLOBAL_REQUEST
string "no-more-sessions@openssh.com"
char want-reply
On receipt of such a message, an OpenSSH server will refuse to open
future channels of type "session" and instead immediately abort the
connection.
Note that this is not a general defence against compromised clients
(that is impossible), but it thwarts a simple attack.
NB. due to certain broken SSH implementations aborting upon receipt
of this message, the no-more-sessions request is only sent to OpenSSH
servers (identified by banner). Other SSH implementations may be
whitelisted to receive this message upon request.
2.3. connection: Tunnel forward extension "tun@openssh.com"
OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com"
channel type. This channel type supports forwarding of network packets
with datagram boundaries intact between endpoints equipped with
interfaces like the BSD tun(4) device. Tunnel forwarding channels are
requested by the client with the following packet:
byte SSH_MSG_CHANNEL_OPEN
string "tun@openssh.com"
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
uint32 tunnel mode
uint32 remote unit number
The "tunnel mode" parameter specifies whether the tunnel should forward
layer 2 frames or layer 3 packets. It may take one of the following values:
SSH_TUNMODE_POINTOPOINT 1 /* layer 3 packets */
SSH_TUNMODE_ETHERNET 2 /* layer 2 frames */
The "tunnel unit number" specifies the remote interface number, or may
be 0x7fffffff to allow the server to automatically chose an interface. A
server that is not willing to open a client-specified unit should refuse
the request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful
open, the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS.
Once established the client and server may exchange packet or frames
over the tunnel channel by encapsulating them in SSH protocol strings
and sending them as channel data. This ensures that packet boundaries
are kept intact. Specifically, packets are transmitted using normal
SSH_MSG_CHANNEL_DATA packets:
byte SSH_MSG_CHANNEL_DATA
uint32 recipient channel
string data
The contents of the "data" field for layer 3 packets is:
uint32 packet length
uint32 address family
byte[packet length - 4] packet data
The "address family" field identifies the type of packet in the message.
It may be one of:
SSH_TUN_AF_INET 2 /* IPv4 */
SSH_TUN_AF_INET6 24 /* IPv6 */
The "packet data" field consists of the IPv4/IPv6 datagram itself
without any link layer header.
The contents of the "data" field for layer 2 packets is:
uint32 packet length
byte[packet length] frame
The "frame" field contains an IEEE 802.3 Ethernet frame, including
header.
2.4. connection: Unix domain socket forwarding
OpenSSH supports local and remote Unix domain socket forwarding
using the "streamlocal" extension. Forwarding is initiated as per
TCP sockets but with a single path instead of a host and port.
Similar to direct-tcpip, direct-streamlocal is sent by the client
to request that the server make a connection to a Unix domain socket.
byte SSH_MSG_CHANNEL_OPEN
string "direct-streamlocal@openssh.com"
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
string socket path
Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
server when the client has previously send the server a streamlocal-forward
GLOBAL_REQUEST.
byte SSH_MSG_CHANNEL_OPEN
string "forwarded-streamlocal@openssh.com"
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
string socket path
string reserved for future use
The reserved field is not currently defined and is ignored on the
remote end. It is intended to be used in the future to pass
information about the socket file, such as ownership and mode.
The client currently sends the empty string for this field.
Similar to tcpip-forward, streamlocal-forward is sent by the client
to request remote forwarding of a Unix domain socket.
byte SSH2_MSG_GLOBAL_REQUEST
string "streamlocal-forward@openssh.com"
boolean TRUE
string socket path
Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent
by the client cancel the forwarding of a Unix domain socket.
byte SSH2_MSG_GLOBAL_REQUEST
string "cancel-streamlocal-forward@openssh.com"
boolean FALSE
string socket path
2.5. connection: hostkey update and rotation "hostkeys-00@openssh.com"
and "hostkeys-prove-00@openssh.com"
OpenSSH supports a protocol extension allowing a server to inform
a client of all its protocol v.2 host keys after user-authentication
has completed.
byte SSH_MSG_GLOBAL_REQUEST
string "hostkeys-00@openssh.com"
string[] hostkeys
Upon receiving this message, a client should check which of the
supplied host keys are present in known_hosts. For keys that are
not present, it should send a "hostkeys-prove@openssh.com" message
to request the server prove ownership of the private half of the
key.
byte SSH_MSG_GLOBAL_REQUEST
string "hostkeys-prove-00@openssh.com"
char 1 /* want-reply */
string[] hostkeys
When a server receives this message, it should generate a signature
using each requested key over the following:
string "hostkeys-prove-00@openssh.com"
string session identifier
string hostkey
These signatures should be included in the reply, in the order matching
the hostkeys in the request:
byte SSH_MSG_REQUEST_SUCCESS
string[] signatures
When the client receives this reply (and not a failure), it should
validate the signatures and may update its known_hosts file, adding keys
that it has not seen before and deleting keys for the server host that
are no longer offered.
These extensions let a client learn key types that it had not previously
encountered, thereby allowing it to potentially upgrade from weaker
key algorithms to better ones. It also supports graceful key rotation:
a server may offer multiple keys of the same type for a period (to
give clients an opportunity to learn them using this extension) before
removing the deprecated key from those offered.
3. SFTP protocol changes
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
When OpenSSH's sftp-server was implemented, the order of the arguments
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
the reversal was not noticed until the server was widely deployed. Since
fixing this to follow the specification would cause incompatibility, the
current order was retained. For correct operation, clients should send
SSH_FXP_SYMLINK as follows:
uint32 id
string targetpath
string linkpath
3.2. sftp: Server extension announcement in SSH_FXP_VERSION
OpenSSH's sftp-server lists the extensions it supports using the
standard extension announcement mechanism in the SSH_FXP_VERSION server
hello packet:
uint32 3 /* protocol version */
string ext1-name
string ext1-version
string ext2-name
string ext2-version
...
string extN-name
string extN-version
Each extension reports its integer version number as an ASCII encoded
string, e.g. "1". The version will be incremented if the extension is
ever changed in an incompatible way. The server MAY advertise the same
extension with multiple versions (though this is unlikely). Clients MUST
check the version number before attempting to use the extension.
3.3. sftp: Extension request "posix-rename@openssh.com"
This operation provides a rename operation with POSIX semantics, which
are different to those provided by the standard SSH_FXP_RENAME in
draft-ietf-secsh-filexfer-02.txt. This request is implemented as a
SSH_FXP_EXTENDED request with the following format:
uint32 id
string "posix-rename@openssh.com"
string oldpath
string newpath
On receiving this request the server will perform the POSIX operation
rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
3.4. sftp: Extension requests "statvfs@openssh.com" and
"fstatvfs@openssh.com"
These requests correspond to the statvfs and fstatvfs POSIX system
interfaces. The "statvfs@openssh.com" request operates on an explicit
pathname, and is formatted as follows:
uint32 id
string "statvfs@openssh.com"
string path
The "fstatvfs@openssh.com" operates on an open file handle:
uint32 id
string "fstatvfs@openssh.com"
string handle
These requests return a SSH_FXP_STATUS reply on failure. On success they
return the following SSH_FXP_EXTENDED_REPLY reply:
uint32 id
uint64 f_bsize /* file system block size */
uint64 f_frsize /* fundamental fs block size */
uint64 f_blocks /* number of blocks (unit f_frsize) */
uint64 f_bfree /* free blocks in file system */
uint64 f_bavail /* free blocks for non-root */
uint64 f_files /* total file inodes */
uint64 f_ffree /* free file inodes */
uint64 f_favail /* free file inodes for to non-root */
uint64 f_fsid /* file system id */
uint64 f_flag /* bit mask of f_flag values */
uint64 f_namemax /* maximum filename length */
The values of the f_flag bitmask are as follows:
#define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */
#define SSH_FXE_STATVFS_ST_NOSUID 0x2 /* no setuid */
Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are
advertised in the SSH_FXP_VERSION hello with version "2".
10. sftp: Extension request "hardlink@openssh.com"
This request is for creating a hard link to a regular file. This
request is implemented as a SSH_FXP_EXTENDED request with the
following format:
uint32 id
string "hardlink@openssh.com"
string oldpath
string newpath
On receiving this request the server will perform the operation
link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
10. sftp: Extension request "fsync@openssh.com"
This request asks the server to call fsync(2) on an open file handle.
uint32 id
string "fsync@openssh.com"
string handle
One receiving this request, a server will call fsync(handle_fd) and will
respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
$OpenBSD: PROTOCOL,v 1.29 2015/07/17 03:09:19 djm Exp $

View File

@@ -0,0 +1,560 @@
This describes the protocol used by OpenSSH's ssh-agent.
OpenSSH's agent supports managing keys for the standard SSH protocol
2 as well as the legacy SSH protocol 1. Support for these key types
is almost completely disjoint - in all but a few cases, operations on
protocol 2 keys cannot see or affect protocol 1 keys and vice-versa.
Protocol 1 and protocol 2 keys are separated because of the differing
cryptographic usage: protocol 1 private RSA keys are used to decrypt
challenges that were encrypted with the corresponding public key,
whereas protocol 2 RSA private keys are used to sign challenges with
a private key for verification with the corresponding public key. It
is considered unsound practice to use the same key for signing and
encryption.
With a couple of exceptions, the protocol message names used in this
document indicate which type of key the message relates to. SSH_*
messages refer to protocol 1 keys only. SSH2_* messages refer to
protocol 2 keys. Furthermore, the names also indicate whether the
message is a request to the agent (*_AGENTC_*) or a reply from the
agent (*_AGENT_*). Section 3 below contains the mapping of the
protocol message names to their integer values.
1. Data types
Because of support for legacy SSH protocol 1 keys, OpenSSH's agent
protocol makes use of some data types not defined in RFC 4251.
1.1 uint16
The "uint16" data type is a simple MSB-first 16 bit unsigned integer
encoded in two bytes.
1.2 mpint1
The "mpint1" type represents an arbitrary precision integer (bignum).
Its format is as follows:
uint16 bits
byte[(bits + 7) / 8] bignum
"bignum" contains an unsigned arbitrary precision integer encoded as
eight bits per byte in big-endian (MSB first) format.
Note the difference between the "mpint1" encoding and the "mpint"
encoding defined in RFC 4251. Also note that the length of the encoded
integer is specified in bits, not bytes and that the byte length of
the integer must be calculated by rounding up the number of bits to the
nearest eight.
2. Protocol Messages
All protocol messages are prefixed with their length in bytes, encoded
as a 32 bit unsigned integer. Specifically:
uint32 message_length
byte[message_length] message
The following message descriptions refer only to the content the
"message" field.
2.1 Generic server responses
The following generic messages may be sent by the server in response to
requests from the client. On success the agent may reply either with:
byte SSH_AGENT_SUCCESS
or a request-specific success message.
On failure, the agent may reply with:
byte SSH_AGENT_FAILURE
SSH_AGENT_FAILURE messages are also sent in reply to unknown request
types.
2.2 Adding keys to the agent
Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and
SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys
respectively.
Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional
"constraints" on their usage.
OpenSSH may be built with support for keys hosted on a smartcard
or other hardware security module. These keys may be added
to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests.
2.2.1 Key constraints
The OpenSSH agent supports some basic optional constraints on key usage.
At present there are two constraints defined.
The first constraint limits the validity duration of a key. It is
encoded as:
byte SSH_AGENT_CONSTRAIN_LIFETIME
uint32 seconds
Where "seconds" contains the number of seconds that the key shall remain
valid measured from the moment that the agent receives it. After the
validity period has expired, OpenSSH's agent will erase these keys from
memory.
The second constraint requires the agent to seek explicit user
confirmation before performing private key operations with the loaded
key. This constraint is encoded as:
byte SSH_AGENT_CONSTRAIN_CONFIRM
Zero or more constraints may be specified when adding a key with one
of the *_CONSTRAINED requests. Multiple constraints are appended
consecutively to the end of the request:
byte constraint1_type
.... constraint1_data
byte constraint2_type
.... constraint2_data
....
byte constraintN_type
.... constraintN_data
Such a sequence of zero or more constraints will be referred to below
as "constraint[]". Agents may determine whether there are constraints
by checking whether additional data exists in the "add key" request
after the key data itself. OpenSSH will refuse to add a key if it
contains unknown constraints.
2.2.2 Add protocol 1 key
A client may add a protocol 1 key to an agent with the following
request:
byte SSH_AGENTC_ADD_RSA_IDENTITY or
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
uint32 ignored
mpint1 rsa_n
mpint1 rsa_e
mpint1 rsa_d
mpint1 rsa_iqmp
mpint1 rsa_q
mpint1 rsa_p
string key_comment
constraint[] key_constraints
Note that there is some redundancy in the key parameters; a key could be
fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
computation.
"key_constraints" may only be present if the request type is
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED.
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
successfully added or a SSH_AGENT_FAILURE if an error occurred.
2.2.3 Add protocol 2 key
The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA
keys may be added using the following request
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-dss"
mpint dsa_p
mpint dsa_q
mpint dsa_g
mpint dsa_public_key
mpint dsa_private_key
string key_comment
constraint[] key_constraints
DSA certificates may be added with:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-dss-cert-v00@openssh.com"
string certificate
mpint dsa_private_key
string key_comment
constraint[] key_constraints
ECDSA keys may be added using the following request
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ecdsa-sha2-nistp256" |
"ecdsa-sha2-nistp384" |
"ecdsa-sha2-nistp521"
string ecdsa_curve_name
string ecdsa_public_key
mpint ecdsa_private
string key_comment
constraint[] key_constraints
ECDSA certificates may be added with:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
"ecdsa-sha2-nistp384-cert-v01@openssh.com" |
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
string certificate
mpint ecdsa_private_key
string key_comment
constraint[] key_constraints
RSA keys may be added with this request:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-rsa"
mpint rsa_n
mpint rsa_e
mpint rsa_d
mpint rsa_iqmp
mpint rsa_p
mpint rsa_q
string key_comment
constraint[] key_constraints
RSA certificates may be added with this request:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-rsa-cert-v00@openssh.com"
string certificate
mpint rsa_d
mpint rsa_iqmp
mpint rsa_p
mpint rsa_q
string key_comment
constraint[] key_constraints
Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse
order to the protocol 1 add keys message. As with the corresponding
protocol 1 "add key" request, the private key is overspecified to avoid
redundant processing.
For DSA, ECDSA and RSA key add requests, "key_constraints" may only be
present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
successfully added or a SSH_AGENT_FAILURE if an error occurred.
2.2.4 Loading keys from a smartcard
The OpenSSH agent may have optional smartcard support built in to it. If
so, it supports an operation to load keys from a smartcard. Technically,
only the public components of the keys are loaded into the agent so
this operation really arranges for future private key operations to be
delegated to the smartcard.
byte SSH_AGENTC_ADD_SMARTCARD_KEY or
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
string reader_id
string pin
constraint[] key_constraints
"reader_id" is an identifier to a smartcard reader and "pin"
is a PIN or passphrase used to unlock the private key(s) on the
device. "key_constraints" may only be present if the request type is
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED.
This operation may load all SSH keys that are unlocked using the
"pin" on the specified reader. The type of key loaded (protocol 1
or protocol 2) will be specified by the smartcard itself, it is not
client-specified.
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
been successfully loaded or a SSH_AGENT_FAILURE if an error occurred.
The agent will also return SSH_AGENT_FAILURE if it does not support
smartcards.
2.3 Removing multiple keys
A client may request that an agent delete all protocol 1 keys using the
following request:
byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
This message requests the deletion of all protocol 2 keys:
byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES
On success, the agent will delete all keys of the requested type and
reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent
will reply with SSH_AGENT_FAILURE.
Note that, to delete all keys (both protocol 1 and 2), a client
must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a
SSH2_AGENTC_REMOVE_ALL_IDENTITIES request.
2.4 Removing specific keys
2.4.1 Removing a protocol 1 key
Removal of a protocol 1 key may be requested with the following message:
byte SSH_AGENTC_REMOVE_RSA_IDENTITY
uint32 key_bits
mpint1 rsa_e
mpint1 rsa_n
Note that key_bits is strictly redundant, as it may be inferred by the
length of rsa_n.
The agent will delete any private key matching the specified public key
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
return SSH_AGENT_FAILURE.
2.4.2 Removing a protocol 2 key
Protocol 2 keys may be removed with the following request:
byte SSH2_AGENTC_REMOVE_IDENTITY
string key_blob
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for any of the supported protocol 2 key types.
The agent will delete any private key matching the specified public key
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
return SSH_AGENT_FAILURE.
2.4.3 Removing keys loaded from a smartcard
A client may request that a server remove one or more smartcard-hosted
keys using this message:
byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
string reader_id
string pin
"reader_id" the an identifier to a smartcard reader and "pin" is a PIN
or passphrase used to unlock the private key(s) on the device.
When this message is received, and if the agent supports
smartcard-hosted keys, it will delete all keys that are hosted on the
specified smartcard that may be accessed with the given "pin".
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
been successfully removed or a SSH_AGENT_FAILURE if an error occurred.
The agent will also return SSH_AGENT_FAILURE if it does not support
smartcards.
2.5 Requesting a list of known keys
An agent may be requested to list which keys it holds. Different
requests exist for protocol 1 and protocol 2 keys.
2.5.1 Requesting a list of protocol 1 keys
To request a list of protocol 1 keys that are held in the agent, a
client may send the following message:
byte SSH_AGENTC_REQUEST_RSA_IDENTITIES
The agent will reply with the following message:
byte SSH_AGENT_RSA_IDENTITIES_ANSWER
uint32 num_keys
Followed by zero or more consecutive keys, encoded as:
uint32 bits
mpint1 rsa_e
mpint1 rsa_n
string key_comment
2.5.2 Requesting a list of protocol 2 keys
A client may send the following message to request a list of
protocol 2 keys that are stored in the agent:
byte SSH2_AGENTC_REQUEST_IDENTITIES
The agent will reply with the following message header:
byte SSH2_AGENT_IDENTITIES_ANSWER
uint32 num_keys
Followed by zero or more consecutive keys, encoded as:
string key_blob
string key_comment
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for any of the supported protocol 2 key types.
2.6 Private key operations
The purpose of the agent is to perform private key operations, such as
signing and encryption without requiring a passphrase to unlock the
key and without allowing the private key itself to be exposed. There
are separate requests for the protocol 1 and protocol 2 private key
operations.
2.6.1 Protocol 1 private key challenge
The private key operation used in version 1 of the SSH protocol is
decrypting a challenge that has been encrypted with a public key.
It may be requested using this message:
byte SSH_AGENTC_RSA_CHALLENGE
uint32 ignored
mpint1 rsa_e
mpint1 rsa_n
mpint1 encrypted_challenge
byte[16] session_id
uint32 response_type /* must be 1 */
"rsa_e" and "rsa_n" are used to identify which private key to use.
"encrypted_challenge" is a challenge blob that has (presumably)
been encrypted with the public key and must be in the range
1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1
session ID (computed from the server host key, the server semi-ephemeral
key and the session cookie).
"ignored" and "response_type" exist for compatibility with legacy
implementations. "response_type" must be equal to 1; other response
types are not supported.
On receiving this request, the server decrypts the "encrypted_challenge"
using the private key matching the supplied (rsa_e, rsa_n) values. For
the response derivation, the decrypted challenge is represented as an
unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values
smaller than 2^248 will have leading 0 bytes).
The response value is then calculated as:
response = MD5(decrypted_challenge || session_id)
and returned in the following message
byte SSH_AGENT_RSA_RESPONSE
byte[16] response
If the agent cannot find the key specified by the supplied (rsa_e,
rsa_n) then it will return SSH_AGENT_FAILURE.
2.6.2 Protocol 2 private key signature request
A client may use the following message to request signing of data using
a protocol 2 key:
byte SSH2_AGENTC_SIGN_REQUEST
string key_blob
string data
uint32 flags
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for any of the supported protocol 2 key types. "flags" is
a bit-mask, but at present only one possible value is defined (see below
for its meaning):
SSH_AGENT_OLD_SIGNATURE 1
Upon receiving this request, the agent will look up the private key that
corresponds to the public key contained in key_blob. It will use this
private key to sign the "data" and produce a signature blob using the
key type-specific method described in RFC 4253 section 6.6 "Public Key
Algorithms".
An exception to this is for "ssh-dss" keys where the "flags" word
contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy
signature encoding is used in lieu of the standard one. In this case,
the DSA signature blob is encoded as:
byte[40] signature
The signature will be returned in the response message:
byte SSH2_AGENT_SIGN_RESPONSE
string signature_blob
If the agent cannot find the key specified by the supplied key_blob then
it will return SSH_AGENT_FAILURE.
2.7 Locking or unlocking an agent
The agent supports temporary locking with a passphrase to suspend
processing of sensitive operations until it has been unlocked with the
same passphrase. To lock an agent, a client send the following request:
byte SSH_AGENTC_LOCK
string passphrase
Upon receipt of this message and if the agent is not already locked,
it will suspend processing requests and return a SSH_AGENT_SUCCESS
reply. If the agent is already locked, it will return SSH_AGENT_FAILURE.
While locked, the agent will refuse all requests except
SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and
SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are
treated specially by a locked agent: it will always return an empty list
of keys.
To unlock an agent, a client may request:
byte SSH_AGENTC_UNLOCK
string passphrase
If the passphrase matches and the agent is locked, then it will resume
processing all requests and return SSH_AGENT_SUCCESS. If the agent
is not locked or the passphrase does not match then it will return
SSH_AGENT_FAILURE.
Locking and unlocking affects both protocol 1 and protocol 2 keys.
3. Protocol message numbers
3.1 Requests from client to agent for protocol 1 key operations
SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
SSH_AGENTC_RSA_CHALLENGE 3
SSH_AGENTC_ADD_RSA_IDENTITY 7
SSH_AGENTC_REMOVE_RSA_IDENTITY 8
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
3.2 Requests from client to agent for protocol 2 key operations
SSH2_AGENTC_REQUEST_IDENTITIES 11
SSH2_AGENTC_SIGN_REQUEST 13
SSH2_AGENTC_ADD_IDENTITY 17
SSH2_AGENTC_REMOVE_IDENTITY 18
SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
SSH2_AGENTC_ADD_ID_CONSTRAINED 25
3.3 Key-type independent requests from client to agent
SSH_AGENTC_ADD_SMARTCARD_KEY 20
SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
SSH_AGENTC_LOCK 22
SSH_AGENTC_UNLOCK 23
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
3.4 Generic replies from agent to client
SSH_AGENT_FAILURE 5
SSH_AGENT_SUCCESS 6
3.5 Replies from agent to client for protocol 1 key operations
SSH_AGENT_RSA_IDENTITIES_ANSWER 2
SSH_AGENT_RSA_RESPONSE 4
3.6 Replies from agent to client for protocol 2 key operations
SSH2_AGENT_IDENTITIES_ANSWER 12
SSH2_AGENT_SIGN_RESPONSE 14
3.7 Key constraint identifiers
SSH_AGENT_CONSTRAIN_LIFETIME 1
SSH_AGENT_CONSTRAIN_CONFIRM 2
$OpenBSD: PROTOCOL.agent,v 1.8 2015/05/08 03:56:51 djm Exp $

View File

@@ -0,0 +1,265 @@
This document describes a simple public-key certificate authentication
system for use by SSH.
Background
----------
The SSH protocol currently supports a simple public key authentication
mechanism. Unlike other public key implementations, SSH eschews the use
of X.509 certificates and uses raw keys. This approach has some benefits
relating to simplicity of configuration and minimisation of attack
surface, but it does not support the important use-cases of centrally
managed, passwordless authentication and centrally certified host keys.
These protocol extensions build on the simple public key authentication
system already in SSH to allow certificate-based authentication. The
certificates used are not traditional X.509 certificates, with numerous
options and complex encoding rules, but something rather more minimal: a
key, some identity information and usage options that have been signed
with some other trusted key.
A sshd server may be configured to allow authentication via certified
keys, by extending the existing ~/.ssh/authorized_keys mechanism to
allow specification of certification authority keys in addition to
raw user keys. The ssh client will support automatic verification of
acceptance of certified host keys, by adding a similar ability to
specify CA keys in ~/.ssh/known_hosts.
Certified keys are represented using new key types:
ssh-rsa-cert-v01@openssh.com
ssh-dss-cert-v01@openssh.com
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384-cert-v01@openssh.com
ecdsa-sha2-nistp521-cert-v01@openssh.com
These include certification information along with the public key
that is used to sign challenges. ssh-keygen performs the CA signing
operation.
Protocol extensions
-------------------
The SSH wire protocol includes several extensibility mechanisms.
These modifications shall take advantage of namespaced public key
algorithm names to add support for certificate authentication without
breaking the protocol - implementations that do not support the
extensions will simply ignore them.
Authentication using the new key formats described below proceeds
using the existing SSH "publickey" authentication method described
in RFC4252 section 7.
New public key formats
----------------------
The certificate key types take a similar high-level format (note: data
types and encoding are as per RFC4251 section 5). The serialised wire
encoding of these certificates is also used for storing them on disk.
#define SSH_CERT_TYPE_USER 1
#define SSH_CERT_TYPE_HOST 2
RSA certificate
string "ssh-rsa-cert-v01@openssh.com"
string nonce
mpint e
mpint n
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
DSA certificate
string "ssh-dss-cert-v01@openssh.com"
string nonce
mpint p
mpint q
mpint g
mpint y
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
ECDSA certificate
string "ecdsa-sha2-nistp256@openssh.com" |
"ecdsa-sha2-nistp384@openssh.com" |
"ecdsa-sha2-nistp521@openssh.com"
string nonce
string curve
string public_key
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
The nonce field is a CA-provided random bitstring of arbitrary length
(but typically 16 or 32 bytes) included to make attacks that depend on
inducing collisions in the signature hash infeasible.
e and n are the RSA exponent and public modulus respectively.
p, q, g, y are the DSA parameters as described in FIPS-186-2.
curve and public key are respectively the ECDSA "[identifier]" and "Q"
defined in section 3.1 of RFC5656.
serial is an optional certificate serial number set by the CA to
provide an abbreviated way to refer to certificates from that CA.
If a CA does not wish to number its certificates it must set this
field to zero.
type specifies whether this certificate is for identification of a user
or a host using a SSH_CERT_TYPE_... value.
key id is a free-form text field that is filled in by the CA at the time
of signing; the intention is that the contents of this field are used to
identify the identity principal in log messages.
"valid principals" is a string containing zero or more principals as
strings packed inside it. These principals list the names for which this
certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and
usernames for SSH_CERT_TYPE_USER certificates. As a special case, a
zero-length "valid principals" field means the certificate is valid for
any principal of the specified type. XXX DNS wildcards?
"valid after" and "valid before" specify a validity period for the
certificate. Each represents a time in seconds since 1970-01-01
00:00:00. A certificate is considered valid if:
valid after <= current time < valid before
criticial options is a set of zero or more key options encoded as
below. All such options are "critical" in the sense that an implementation
must refuse to authorise a key that has an unrecognised option.
extensions is a set of zero or more optional extensions. These extensions
are not critical, and an implementation that encounters one that it does
not recognise may safely ignore it.
Generally, critical options are used to control features that restrict
access where extensions are used to enable features that grant access.
This ensures that certificates containing unknown restrictions do not
inadvertently grant access while allowing new protocol features to be
enabled via extensions without breaking certificates' backwards
compatibility.
The reserved field is currently unused and is ignored in this version of
the protocol.
signature key contains the CA key used to sign the certificate.
The valid key types for CA keys are ssh-rsa, ssh-dss and the ECDSA types
ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained"
certificates, where the signature key type is a certificate type itself
are NOT supported. Note that it is possible for a RSA certificate key to
be signed by a DSS or ECDSA CA key and vice-versa.
signature is computed over all preceding fields from the initial string
up to, and including the signature key. Signatures are computed and
encoded according to the rules defined for the CA's public key algorithm
(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA
types).
Critical options
----------------
The critical options section of the certificate specifies zero or more
options on the certificates validity. The format of this field
is a sequence of zero or more tuples:
string name
string data
Options must be lexically ordered by "name" if they appear in the
sequence. Each named option may only appear once in a certificate.
The name field identifies the option and the data field encodes
option-specific information (see below). All options are
"critical", if an implementation does not recognise a option
then the validating party should refuse to accept the certificate.
The supported options and the contents and structure of their
data fields are:
Name Format Description
-----------------------------------------------------------------------------
force-command string Specifies a command that is executed
(replacing any the user specified on the
ssh command-line) whenever this key is
used for authentication.
source-address string Comma-separated list of source addresses
from which this certificate is accepted
for authentication. Addresses are
specified in CIDR format (nn.nn.nn.nn/nn
or hhhh::hhhh/nn).
If this option is not present then
certificates may be presented from any
source address.
Extensions
----------
The extensions section of the certificate specifies zero or more
non-critical certificate extensions. The encoding and ordering of
extensions in this field is identical to that of the critical options,
as is the requirement that each name appear only once.
If an implementation does not recognise an extension, then it should
ignore it.
The supported extensions and the contents and structure of their data
fields are:
Name Format Description
-----------------------------------------------------------------------------
permit-X11-forwarding empty Flag indicating that X11 forwarding
should be permitted. X11 forwarding will
be refused if this option is absent.
permit-agent-forwarding empty Flag indicating that agent forwarding
should be allowed. Agent forwarding
must not be permitted unless this
option is present.
permit-port-forwarding empty Flag indicating that port-forwarding
should be allowed. If this option is
not present then no port forwarding will
be allowed.
permit-pty empty Flag indicating that PTY allocation
should be permitted. In the absence of
this option PTY allocation will be
disabled.
permit-user-rc empty Flag indicating that execution of
~/.ssh/rc should be permitted. Execution
of this script will not be permitted if
this option is not present.
$OpenBSD: PROTOCOL.certkeys,v 1.9 2012/03/28 07:23:22 djm Exp $

View File

@@ -0,0 +1,105 @@
This document describes the chacha20-poly1305@openssh.com authenticated
encryption cipher supported by OpenSSH.
Background
----------
ChaCha20 is a stream cipher designed by Daniel Bernstein and described
in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key,
a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output
is used as a keystream, with any unused bytes simply discarded.
Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC
that computes a 128 bit integrity tag given a message and a single-use
256 bit secret key.
The chacha20-poly1305@openssh.com combines these two primitives into an
authenticated encryption mode. The construction used is based on that
proposed for TLS by Adam Langley in [3], but differs in the layout of
data passed to the MAC and in the addition of encyption of the packet
lengths.
Negotiation
-----------
The chacha20-poly1305@openssh.com offers both encryption and
authentication. As such, no separate MAC is required. If the
chacha20-poly1305@openssh.com cipher is selected in key exchange,
the offered MAC algorithms are ignored and no MAC is required to be
negotiated.
Detailed Construction
---------------------
The chacha20-poly1305@openssh.com cipher requires 512 bits of key
material as output from the SSH key exchange. This forms two 256 bit
keys (K_1 and K_2), used by two separate instances of chacha20.
The instance keyed by K_1 is a stream cipher that is used only
to encrypt the 4 byte packet length field. The second instance,
keyed by K_2, is used in conjunction with poly1305 to build an AEAD
(Authenticated Encryption with Associated Data) that is used to encrypt
and authenticate the entire packet.
Two separate cipher instances are used here so as to keep the packet
lengths confidential but not create an oracle for the packet payload
cipher by decrypting and using the packet length prior to checking
the MAC. By using an independently-keyed cipher instance to encrypt the
length, an active attacker seeking to exploit the packet input handling
as a decryption oracle can learn nothing about the payload contents or
its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure).
The AEAD is constructed as follows: for each packet, generate a Poly1305
key by taking the first 256 bits of ChaCha20 stream output generated
using K_2, an IV consisting of the packet sequence number encoded as an
uint64 under the SSH wire encoding rules and a ChaCha20 block counter of
zero. The K_2 ChaCha20 block counter is then set to the little-endian
encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used
for encryption of the packet payload.
Packet Handling
---------------
When receiving a packet, the length must be decrypted first. When 4
bytes of ciphertext length have been received, they may be decrypted
using the K_1 key, a nonce consisting of the packet sequence number
encoded as a uint64 under the usual SSH wire encoding and a zero block
counter to obtain the plaintext length.
Once the entire packet has been received, the MAC MUST be checked
before decryption. A per-packet Poly1305 key is generated as described
above and the MAC tag calculated using Poly1305 with this key over the
ciphertext of the packet length and the payload together. The calculated
MAC is then compared in constant time with the one appended to the
packet and the packet decrypted using ChaCha20 as described above (with
K_2, the packet sequence number as nonce and a starting block counter of
1).
To send a packet, first encode the 4 byte length and encrypt it using
K_1. Encrypt the packet payload (using K_2) and append it to the
encrypted length. Finally, calculate a MAC tag and append it.
Rekeying
--------
ChaCha20 must never reuse a {key, nonce} for encryption nor may it be
used to encrypt more than 2^70 bytes under the same {key, nonce}. The
SSH Transport protocol (RFC4253) recommends a far more conservative
rekeying every 1GB of data sent or received. If this recommendation
is followed, then chacha20-poly1305@openssh.com requires no special
handling in this area.
References
----------
[1] "ChaCha, a variant of Salsa20", Daniel Bernstein
http://cr.yp.to/chacha/chacha-20080128.pdf
[2] "The Poly1305-AES message-authentication code", Daniel Bernstein
http://cr.yp.to/mac/poly1305-20050329.pdf
[3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley
http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03
$OpenBSD: PROTOCOL.chacha20poly1305,v 1.2 2013/12/02 02:50:27 djm Exp $

View File

@@ -0,0 +1,68 @@
This document describes the private key format for OpenSSH.
1. Overall format
The key consists of a header, a list of public keys, and
an encrypted list of matching private keys.
#define AUTH_MAGIC "openssh-key-v1"
byte[] AUTH_MAGIC
string ciphername
string kdfname
string kdfoptions
int number of keys N
string publickey1
string publickey2
...
string publickeyN
string encrypted, padded list of private keys
2. KDF options for kdfname "bcrypt"
The options:
string salt
uint32 rounds
are concatenated and represented as a string.
3. Unencrypted list of N private keys
The list of privatekey/comment pairs is padded with the
bytes 1, 2, 3, ... until the total length is a multiple
of the cipher block size.
uint32 checkint
uint32 checkint
string privatekey1
string comment1
string privatekey2
string comment2
...
string privatekeyN
string commentN
char 1
char 2
char 3
...
char padlen % 255
Before the key is encrypted, a random integer is assigned
to both checkint fields so successful decryption can be
quickly checked by verifying that both checkint fields
hold the same value.
4. Encryption
The KDF is used to derive a key, IV (and other values required by
the cipher) from the passphrase. These values are then used to
encrypt the unencrypted list of private keys.
5. No encryption
For unencrypted keys the cipher "none" and the KDF "none"
are used with empty passphrases. The options if the KDF "none"
are the empty string.
$OpenBSD: PROTOCOL.key,v 1.1 2013/12/06 13:34:54 markus Exp $

View File

@@ -0,0 +1,169 @@
This describes the key/certificate revocation list format for OpenSSH.
1. Overall format
The KRL consists of a header and zero or more sections. The header is:
#define KRL_MAGIC 0x5353484b524c0a00ULL /* "SSHKRL\n\0" */
#define KRL_FORMAT_VERSION 1
uint64 KRL_MAGIC
uint32 KRL_FORMAT_VERSION
uint64 krl_version
uint64 generated_date
uint64 flags
string reserved
string comment
Where "krl_version" is a version number that increases each time the KRL
is modified, "generated_date" is the time in seconds since 1970-01-01
00:00:00 UTC that the KRL was generated, "comment" is an optional comment
and "reserved" an extension field whose contents are currently ignored.
No "flags" are currently defined.
Following the header are zero or more sections, each consisting of:
byte section_type
string section_data
Where "section_type" indicates the type of the "section_data". An exception
to this is the KRL_SECTION_SIGNATURE section, that has a slightly different
format (see below).
The available section types are:
#define KRL_SECTION_CERTIFICATES 1
#define KRL_SECTION_EXPLICIT_KEY 2
#define KRL_SECTION_FINGERPRINT_SHA1 3
#define KRL_SECTION_SIGNATURE 4
2. Certificate section
These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by
serial number or key ID. The consist of the CA key that issued the
certificates to be revoked and a reserved field whose contents is currently
ignored.
string ca_key
string reserved
Where "ca_key" is the standard SSH wire serialisation of the CA's
public key. Alternately, "ca_key" may be an empty string to indicate
the certificate section applies to all CAs (this is most useful when
revoking key IDs).
Followed by one or more sections:
byte cert_section_type
string cert_section_data
The certificate section types are:
#define KRL_SECTION_CERT_SERIAL_LIST 0x20
#define KRL_SECTION_CERT_SERIAL_RANGE 0x21
#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
#define KRL_SECTION_CERT_KEY_ID 0x23
2.1 Certificate serial list section
This section is identified as KRL_SECTION_CERT_SERIAL_LIST. It revokes
certificates by listing their serial numbers. The cert_section_data in this
case contains:
uint64 revoked_cert_serial
uint64 ...
This section may appear multiple times.
2.2. Certificate serial range section
These sections use type KRL_SECTION_CERT_SERIAL_RANGE and hold
a range of serial numbers of certificates:
uint64 serial_min
uint64 serial_max
All certificates in the range serial_min <= serial <= serial_max are
revoked.
This section may appear multiple times.
2.3. Certificate serial bitmap section
Bitmap sections use type KRL_SECTION_CERT_SERIAL_BITMAP and revoke keys
by listing their serial number in a bitmap.
uint64 serial_offset
mpint revoked_keys_bitmap
A bit set at index N in the bitmap corresponds to revocation of a keys with
serial number (serial_offset + N).
This section may appear multiple times.
2.4. Revoked key ID sections
KRL_SECTION_CERT_KEY_ID sections revoke particular certificate "key
ID" strings. This may be useful in revoking all certificates
associated with a particular identity, e.g. a host or a user.
string key_id[0]
...
This section must contain at least one "key_id". This section may appear
multiple times.
3. Explicit key sections
These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys
(not certificates). They are less space efficient than serial numbers,
but are able to revoke plain keys.
string public_key_blob[0]
....
This section must contain at least one "public_key_blob". The blob
must be a raw key (i.e. not a certificate).
This section may appear multiple times.
4. SHA1 fingerprint sections
These sections, identified as KRL_SECTION_FINGERPRINT_SHA1, revoke
plain keys (i.e. not certificates) by listing their SHA1 hashes:
string public_key_hash[0]
....
This section must contain at least one "public_key_hash". The hash blob
is obtained by taking the SHA1 hash of the public key blob. Hashes in
this section must appear in numeric order, treating each hash as a big-
endian integer.
This section may appear multiple times.
5. KRL signature sections
The KRL_SECTION_SIGNATURE section serves a different purpose to the
preceeding ones: to provide cryptographic authentication of a KRL that
is retrieved over a channel that does not provide integrity protection.
Its format is slightly different to the previously-described sections:
in order to simplify the signature generation, it includes as a "body"
two string components instead of one.
byte KRL_SECTION_SIGNATURE
string signature_key
string signature
The signature is calculated over the entire KRL from the KRL_MAGIC
to this subsection's "signature_key", including both and using the
signature generation rules appropriate for the type of "signature_key".
This section must appear last in the KRL. If multiple signature sections
appear, they must appear consecutively at the end of the KRL file.
Implementations that retrieve KRLs over untrusted channels must verify
signatures. Signature sections are optional for KRLs distributed by
trusted means.
$OpenBSD: PROTOCOL.krl,v 1.3 2015/01/30 01:10:33 djm Exp $

View File

@@ -0,0 +1,228 @@
This document describes the multiplexing protocol used by ssh(1)'s
ControlMaster connection-sharing.
Most messages from the client to the server contain a "request id" field.
This field is returned in replies as "client request id" to facilitate
matching of responses to requests.
1. Connection setup
When a multiplexing connection is made to a ssh(1) operating as a
ControlMaster from a ssh(1) in multiplex slave mode, the first
action of each is to exchange hello messages:
uint32 MUX_MSG_HELLO
uint32 protocol version
string extension name [optional]
string extension value [optional]
...
The current version of the mux protocol is 4. A slave should refuse
to connect to a master that speaks an unsupported protocol version.
Following the version identifier are zero or more extensions
represented as a name/value pair. No extensions are currently
defined.
2. Opening sessions
To open a new multiplexed session, a client may send the following
request:
uint32 MUX_C_NEW_SESSION
uint32 request id
string reserved
bool want tty flag
bool want X11 forwarding flag
bool want agent flag
bool subsystem flag
uint32 escape char
string terminal type
string command
string environment string 0 [optional]
...
To disable the use of an escape character, "escape char" may be set
to 0xffffffff. "terminal type" is generally set to the value of
$TERM. zero or more environment strings may follow the command.
The client then sends its standard input, output and error file
descriptors (in that order) using Unix domain socket control messages.
The contents of "reserved" are currently ignored.
If successful, the server will reply with MUX_S_SESSION_OPENED
uint32 MUX_S_SESSION_OPENED
uint32 client request id
uint32 session id
Otherwise it will reply with an error: MUX_S_PERMISSION_DENIED or
MUX_S_FAILURE.
Once the server has received the fds, it will respond with MUX_S_OK
indicating that the session is up. The client now waits for the
session to end. When it does, the server will send an exit status
message:
uint32 MUX_S_EXIT_MESSAGE
uint32 session id
uint32 exit value
The client should exit with this value to mimic the behaviour of a
non-multiplexed ssh(1) connection. Two additional cases that the
client must cope with are it receiving a signal itself and the
server disconnecting without sending an exit message.
A master may also send a MUX_S_TTY_ALLOC_FAIL before MUX_S_EXIT_MESSAGE
if remote TTY allocation was unsuccessful. The client may use this to
return its local tty to "cooked" mode.
uint32 MUX_S_TTY_ALLOC_FAIL
uint32 session id
3. Health checks
The client may request a health check/PID report from a server:
uint32 MUX_C_ALIVE_CHECK
uint32 request id
The server replies with:
uint32 MUX_S_ALIVE
uint32 client request id
uint32 server pid
4. Remotely terminating a master
A client may request that a master terminate immediately:
uint32 MUX_C_TERMINATE
uint32 request id
The server will reply with one of MUX_S_OK or MUX_S_PERMISSION_DENIED.
5. Requesting establishment of port forwards
A client may request the master to establish a port forward:
uint32 MUX_C_OPEN_FWD
uint32 request id
uint32 forwarding type
string listen host
uint32 listen port
string connect host
uint32 connect port
forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC.
If listen port is (unsigned int) -2, then the listen host is treated as
a unix socket path name.
If connect port is (unsigned int) -2, then the connect host is treated
as a unix socket path name.
A server may reply with a MUX_S_OK, a MUX_S_REMOTE_PORT, a
MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE.
For dynamically allocated listen port the server replies with
uint32 MUX_S_REMOTE_PORT
uint32 client request id
uint32 allocated remote listen port
6. Requesting closure of port forwards
Note: currently unimplemented (server will always reply with MUX_S_FAILURE).
A client may request the master to close a port forward:
uint32 MUX_C_CLOSE_FWD
uint32 request id
uint32 forwarding type
string listen host
uint32 listen port
string connect host
uint32 connect port
A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
MUX_S_FAILURE.
7. Requesting stdio forwarding
A client may request the master to establish a stdio forwarding:
uint32 MUX_C_NEW_STDIO_FWD
uint32 request id
string reserved
string connect host
string connect port
The client then sends its standard input and output file descriptors
(in that order) using Unix domain socket control messages.
The contents of "reserved" are currently ignored.
A server may reply with a MUX_S_SESSION_OPENED, a MUX_S_PERMISSION_DENIED
or a MUX_S_FAILURE.
8. Requesting shutdown of mux listener
A client may request the master to stop accepting new multiplexing requests
and remove its listener socket.
uint32 MUX_C_STOP_LISTENING
uint32 request id
A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
MUX_S_FAILURE.
9. Status messages
The MUX_S_OK message is empty:
uint32 MUX_S_OK
uint32 client request id
The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
uint32 MUX_S_PERMISSION_DENIED
uint32 client request id
string reason
uint32 MUX_S_FAILURE
uint32 client request id
string reason
10. Protocol numbers
#define MUX_MSG_HELLO 0x00000001
#define MUX_C_NEW_SESSION 0x10000002
#define MUX_C_ALIVE_CHECK 0x10000004
#define MUX_C_TERMINATE 0x10000005
#define MUX_C_OPEN_FWD 0x10000006
#define MUX_C_CLOSE_FWD 0x10000007
#define MUX_C_NEW_STDIO_FWD 0x10000008
#define MUX_C_STOP_LISTENING 0x10000009
#define MUX_S_OK 0x80000001
#define MUX_S_PERMISSION_DENIED 0x80000002
#define MUX_S_FAILURE 0x80000003
#define MUX_S_EXIT_MESSAGE 0x80000004
#define MUX_S_ALIVE 0x80000005
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
#define MUX_S_TTY_ALLOC_FAIL 0x80000008
#define MUX_FWD_LOCAL 1
#define MUX_FWD_REMOTE 2
#define MUX_FWD_DYNAMIC 3
XXX TODO
XXX extended status (e.g. report open channels / forwards)
XXX lock (maybe)
XXX watch in/out traffic (pre/post crypto)
XXX inject packet (what about replies)
XXX server->client error/warning notifications
XXX send signals via mux
$OpenBSD: PROTOCOL.mux,v 1.10 2015/07/17 03:04:27 djm Exp $

69
crypto/external/bsd/openssh/dist/README vendored Normal file
View File

@@ -0,0 +1,69 @@
See http://www.openssh.com/txt/release-7.1 for the release notes.
Please read http://www.openssh.com/report.html for bug reporting
instructions and note that we do not use Github for bug reporting or
patch/pull-request management.
- A Japanese translation of this document and of the OpenSSH FAQ is
- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
- Thanks to HARUYAMA Seigo <haruyama@unixuser.org>
This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other
Unices.
OpenSSH is based on the last free version of Tatu Ylonen's sample
implementation with all patent-encumbered algorithms removed (to
external libraries), all known security bugs fixed, new features
reintroduced and many other clean-ups. OpenSSH has been created by
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt,
and Dug Song. It has a homepage at http://www.openssh.com/
This port consists of the re-introduction of autoconf support, PAM
support, EGD[1]/PRNGD[2] support and replacements for OpenBSD library
functions that are (regrettably) absent from other unices. This port
has been best tested on AIX, Cygwin, HP-UX, Linux, MacOS/X,
NetBSD, OpenBSD, OpenServer, Solaris, Unicos, and UnixWare.
This version actively tracks changes in the OpenBSD CVS repository.
The PAM support is now more functional than the popular packages of
commercial ssh-1.2.x. It checks "account" and "session" modules for
all logins, not just when using password authentication.
OpenSSH depends on Zlib[3], OpenSSL[4] and optionally PAM[5].
There is now several mailing lists for this port of OpenSSH. Please
refer to http://www.openssh.com/list.html for details on how to join.
Please send bug reports and patches to the mailing list
openssh-unix-dev@mindrot.org. The list is open to posting by
unsubscribed users.Code contribution are welcomed, but please follow the
OpenBSD style guidelines[6].
Please refer to the INSTALL document for information on how to install
OpenSSH on your system. There are a number of differences between this
port of OpenSSH and F-Secure SSH 1.x, please refer to the OpenSSH FAQ[7]
for details and general tips.
Damien Miller <djm@mindrot.org>
Miscellania -
This version of OpenSSH is based upon code retrieved from the OpenBSD
CVS repository which in turn was based on the last free sample
implementation released by Tatu Ylonen.
References -
[0] http://www.openssh.com/faq.html
[1] http://www.lothar.com/tech/crypto/
[2] http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html
[3] http://www.gzip.org/zlib/
[4] http://www.openssl.org/
[5] http://www.openpam.org
http://www.kernel.org/pub/linux/libs/pam/
(PAM also is standard on Solaris and HP-UX 11)
[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
[7] http://www.openssh.com/faq.html
$Id: README,v 1.87 2014/08/10 01:35:06 djm Exp $

View File

@@ -0,0 +1,47 @@
How to verify host keys using OpenSSH and DNS
---------------------------------------------
OpenSSH contains support for verifying host keys using DNS as described in
draft-ietf-secsh-dns-05.txt. The document contains very brief instructions
on how to use this feature. Configuring DNS is out of the scope of this
document.
(1) Server: Generate and publish the DNS RR
To create a DNS resource record (RR) containing a fingerprint of the
public host key, use the following command:
ssh-keygen -r hostname -f keyfile -g
where "hostname" is your fully qualified hostname and "keyfile" is the
file containing the public host key file. If you have multiple keys,
you should generate one RR for each key.
In the example above, ssh-keygen will print the fingerprint in a
generic DNS RR format parsable by most modern name server
implementations. If your nameserver has support for the SSHFP RR
you can omit the -g flag and ssh-keygen will print a standard SSHFP RR.
To publish the fingerprint using the DNS you must add the generated RR
to your DNS zone file and sign your zone.
(2) Client: Enable ssh to verify host keys using DNS
To enable the ssh client to verify host keys using DNS, you have to
add the following option to the ssh configuration file
($HOME/.ssh/config or /etc/ssh/ssh_config):
VerifyHostKeyDNS yes
Upon connection the client will try to look up the fingerprint RR
using DNS. If the fingerprint received from the DNS server matches
the remote host key, the user will be notified.
Jakob Schlyter
Wesley Griffin
$OpenBSD: README.dns,v 1.2 2003/10/14 19:43:23 jakob Exp $

View File

@@ -0,0 +1,267 @@
OpenSSH LDAP PUBLIC KEY PATCH
Copyright (c) 2003 Eric AUGE (eau@phear.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
purposes of this patch:
This patch would help to have authentication centralization policy
using ssh public key authentication.
This patch could be an alternative to other "secure" authentication system
working in a similar way (Kerberos, SecurID, etc...), except the fact
that it's based on OpenSSH and its public key abilities.
>> FYI: <<
'uid': means unix accounts existing on the current server
'lpkServerGroup:' mean server group configured on the current server ('lpkServerGroup' in sshd_config)
example schema:
server1 (uid: eau,rival,toto) (lpkServerGroup: unix)
___________ /
/ \ --- - server3 (uid: eau, titi) (lpkServerGroup: unix)
| LDAP Server | \
| eau ,rival | server2 (uid: rival, eau) (lpkServerGroup: unix)
| titi ,toto |
| userx,.... | server5 (uid: eau) (lpkServerGroup: mail)
\___________/ \ /
----- - server4 (uid: eau, rival) (no group configured)
\
etc...
- WHAT WE NEED :
* configured LDAP server somewhere on the network (i.e. OpenLDAP)
* patched sshd (with this patch ;)
* LDAP user(/group) entry (look at users.ldif (& groups.ldif)):
User entry:
- attached to the 'ldapPublicKey' objectclass
- attached to the 'posixAccount' objectclass
- with a filled 'sshPublicKey' attribute
Example:
dn: uid=eau,ou=users,dc=cuckoos,dc=net
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: posixAccount
objectclass: ldapPublicKey
description: Eric AUGE Account
userPassword: blah
cn: Eric AUGE
sn: Eric AUGE
uid: eau
uidNumber: 1034
gidNumber: 1
homeDirectory: /export/home/eau
sshPublicKey: ssh-dss AAAAB3...
sshPublicKey: ssh-dss AAAAM5...
Group entry:
- attached to the 'posixGroup' objectclass
- with a 'cn' groupname attribute
- with multiple 'memberUid' attributes filled with usernames allowed in this group
Example:
# few members
dn: cn=unix,ou=groups,dc=cuckoos,dc=net
objectclass: top
objectclass: posixGroup
description: Unix based servers group
cn: unix
gidNumber: 1002
memberUid: eau
memberUid: user1
memberUid: user2
- HOW IT WORKS :
* without patch
If a user wants to authenticate to log in a server the sshd, will first look for authentication method allowed (RSAauth,kerberos,etc..)
and if RSAauth and tickets based auth fails, it will fallback to standard password authentication (if enabled).
* with the patch
If a user want to authenticate to log in a server, the sshd will first look for auth method including LDAP pubkey, if the ldappubkey options is enabled.
It will do an ldapsearch to get the public key directly from the LDAP instead of reading it from the server filesystem.
(usually in $HOME/.ssh/authorized_keys)
If groups are enabled, it will also check if the user that wants to login is in the group of the server he is trying to log into.
If it fails, it falls back on RSA auth files ($HOME/.ssh/authorized_keys), etc.. and finally to standard password authentication (if enabled).
7 tokens are added to sshd_config :
# here is the new patched ldap related tokens
# entries in your LDAP must be posixAccount & strongAuthenticationUser & posixGroup
UseLPK yes # look the pub key into LDAP
LpkServers ldap://10.31.32.5/ ldap://10.31.32.4 ldap://10.31.32.3 # which LDAP server for users ? (URL format)
LpkUserDN ou=users,dc=foobar,dc=net # which base DN for users ?
LpkGroupDN ou=groups,dc=foobar,dc=net # which base DN for groups ?
LpkBindDN cn=manager,dc=foobar,dc=net # which bind DN ?
LpkBindPw asecret # bind DN credidentials
LpkServerGroup agroupname # the group the server is part of
Right now i'm using anonymous binding to get public keys, because getting public keys of someone doesn't impersonate him¸ but there is some
flaws you have to take care of.
- HOW TO INSERT A USER/KEY INTO AN LDAP ENTRY
* my way (there is plenty :)
- create ldif file (i.e. users.ldif)
- cat ~/.ssh/id_dsa.pub OR cat ~/.ssh/id_rsa.pub OR cat ~/.ssh/identity.pub
- my way in 4 steps :
Example:
# you add this to the user entry in the LDIF file :
[...]
objectclass: posixAccount
objectclass: ldapPublicKey
[...]
sshPubliKey: ssh-dss AAAABDh12DDUR2...
[...]
# insert your entry and you're done :)
ldapadd -D balblabla -w bleh < file.ldif
all standard options can be present in the 'sshPublicKey' attribute.
- WHY :
Simply because, i was looking for a way to centralize all sysadmins authentication, easily, without completely using LDAP
as authentication method (like pam_ldap etc..).
After looking into Kerberos, SecurID, and other centralized secure authentications systems, the use of RSA and LDAP to get
public key for authentication allows us to control who has access to which server (the user needs an account and to be in 'strongAuthenticationUser'
objectclass within LDAP and part of the group the SSH server is in).
Passwords update are no longer a nightmare for a server farm (key pair passphrase is stored on each user's box and private key is locally encrypted using his passphrase
so each user can change it as much as he wants).
Blocking a user account can be done directly from the LDAP (if sshd is using RSAAuth + ldap only).
- RULES :
Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema.
and the additionnal lpk.schema.
This patch could allow a smooth transition between standard auth (/etc/passwd) and complete LDAP based authentication
(pamldap, nss_ldap, etc..).
This can be an alternative to other (old?/expensive?) authentication methods (Kerberos/SecurID/..).
Referring to schema at the beginning of this file if user 'eau' is only in group 'unix'
'eau' would ONLY access 'server1', 'server2', 'server3' AND 'server4' BUT NOT 'server5'.
If you then modify the LDAP 'mail' group entry to add 'memberUid: eau' THEN user 'eau' would be able
to log in 'server5' (i hope you got the idea, my english is bad :).
Each server's sshd is patched and configured to ask the public key and the group infos in the LDAP
server.
When you want to allow a new user to have access to the server parc, you just add him an account on
your servers, you add his public key into his entry on the LDAP server, it's done.
Because sshds are looking public keys into the LDAP directly instead of a file ($HOME/.ssh/authorized_keys).
When the user needs to change his passphrase he can do it directly from his workstation by changing
his own key set lock passphrase, and all servers are automatically aware.
With a CAREFUL LDAP server configuration you could allow a user to add/delete/modify his own entry himself
so he can add/modify/delete himself his public key when needed.
­ FLAWS :
LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP
allow write to users dn, somebody could replace someuser's public key by its own and impersonate some
of your users in all your server farm be VERY CAREFUL.
MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login
as the impersonnated user.
If LDAP server is down then, fallback on passwd auth.
the ldap code part has not been well audited yet.
- LDAP USER ENTRY EXAMPLES (LDIF Format, look in users.ldif)
--- CUT HERE ---
dn: uid=jdoe,ou=users,dc=foobar,dc=net
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: posixAccount
objectclass: ldapPublicKey
description: My account
cn: John Doe
sn: John Doe
uid: jdoe
uidNumber: 100
gidNumber: 100
homeDirectory: /home/jdoe
sshPublicKey: ssh-dss AAAAB3NzaC1kc3MAAAEBAOvL8pREUg9wSy/8+hQJ54YF3AXkB0OZrXB....
[...]
--- CUT HERE ---
- LDAP GROUP ENTRY EXAMPLES (LDIF Format, look in groups.ldif)
--- CUT HERE ---
dn: cn=unix,ou=groups,dc=cuckoos,dc=net
objectclass: top
objectclass: posixGroup
description: Unix based servers group
cn: unix
gidNumber: 1002
memberUid: jdoe
memberUid: user1
memberUid: user2
[...]
--- CUT HERE ---
>> FYI: <<
Multiple 'sshPublicKey' in a user entry are allowed, as well as multiple 'memberUid' attributes in a group entry
- COMPILING:
1. Apply the patch
2. ./configure --with-your-options --with-ldap=/prefix/to/ldap_libs_and_includes
3. make
4. it's done.
- BLA :
I hope this could help, and i hope to be clear enough,, or give ideas. questions/comments/improvements are welcome.
- TODO :
Redesign differently.
- DOCS/LINK :
http://pacsec.jp/core05/psj05-barisani-en.pdf
http://fritz.potsdam.edu/projects/openssh-lpk/
http://fritz.potsdam.edu/projects/sshgate/
http://dev.inversepath.com/trac/openssh-lpk
http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm )
- CONTRIBUTORS/IDEAS/GREETS :
- Falk Siemonsmeier.
- Jacob Rief.
- Michael Durchgraf.
- frederic peters.
- Finlay dobbie.
- Stefan Fisher.
- Robin H. Johnson.
- Adrian Bridgett.
- CONTACT :
- Eric AUGE <eau@phear.org>
- Andrea Barisani <andrea@inversepath.com>

View File

@@ -0,0 +1,96 @@
This file contains notes about OpenSSH on specific platforms.
AIX
---
As of OpenSSH 3.8p1, sshd will now honour an accounts password expiry
settings, where previously it did not. Because of this, it's possible for
sites that have used OpenSSH's sshd exclusively to have accounts which
have passwords expired longer than the inactive time (ie the "Weeks between
password EXPIRATION and LOCKOUT" setting in SMIT or the maxexpired
chuser attribute).
Accounts in this state must have their passwords reset manually by the
administrator. As a precaution, it is recommended that the administrative
passwords be reset before upgrading from OpenSSH <3.8.
As of OpenSSH 4.0, configure will attempt to detect if your version
and maintenance level of AIX has a working getaddrinfo, and will use it
if found. This will enable IPv6 support. If for some reason configure
gets it wrong, or if you want to build binaries to work on earlier MLs
than the build host then you can add "-DBROKEN_GETADDRINFO" to CFLAGS
to force the previous IPv4-only behaviour.
IPv6 known to work: 5.1ML7 5.2ML2 5.2ML5
IPv6 known broken: 4.3.3ML11 5.1ML4
If you wish to use dynamic libraries that aren't in the normal system
locations (eg IBM's OpenSSL and zlib packages) then you will need to
define the environment variable blibpath before running configure, eg
blibpath=/lib:/usr/lib:/opt/freeware/lib ./configure \
--with-ssl-dir=/opt/freeware --with-zlib=/opt/freeware
If sshd is built with the WITH_AIXAUTHENTICATE option (which is enabled
by default) then sshd checks that users are permitted via the
loginrestrictions() function, in particular that the user has the
"rlogin" attribute set. This check is not done for the root account,
instead the PermitRootLogin setting in sshd_config is used.
Cygwin
------
To build on Cygwin, OpenSSH requires the following packages:
gcc, gcc-mingw-core, mingw-runtime, binutils, make, openssl,
openssl-devel, zlib, minres, minires-devel.
Darwin and MacOS X
------------------
Darwin does not provide a tun(4) driver required for OpenSSH-based
virtual private networks. The BSD manpage still exists, but the driver
has been removed in recent releases of Darwin and MacOS X.
Nevertheless, tunnel support is known to work with Darwin 8 and
MacOS X 10.4 in Point-to-Point (Layer 3) and Ethernet (Layer 2) mode
using a third party driver. More information is available at:
http://www-user.rhrk.uni-kl.de/~nissler/tuntap/
Linux
-----
Some Linux distributions (including Red Hat/Fedora/CentOS) include
headers and library links in the -devel RPMs rather than the main
binary RPMs. If you get an error about headers, or complaining about a
missing prerequisite then you may need to install the equivalent
development packages. On Redhat based distros these may be openssl-devel,
zlib-devel and pam-devel, on Debian based distros these may be
libssl-dev, libz-dev and libpam-dev.
Solaris
-------
If you enable BSM auditing on Solaris, you need to update audit_event(4)
for praudit(1m) to give sensible output. The following line needs to be
added to /etc/security/audit_event:
32800:AUE_openssh:OpenSSH login:lo
The BSM audit event range available for third party TCB applications is
32768 - 65535. Event number 32800 has been choosen for AUE_openssh.
There is no official registry of 3rd party event numbers, so if this
number is already in use on your system, you may change it at build time
by configure'ing --with-cflags=-DAUE_openssh=32801 then rebuilding.
Platforms using PAM
-------------------
As of OpenSSH 4.3p1, sshd will no longer check /etc/nologin itself when
PAM is enabled. To maintain existing behaviour, pam_nologin should be
added to sshd's session stack which will prevent users from starting shell
sessions. Alternatively, pam_nologin can be added to either the auth or
account stacks which will prevent authentication entirely, but will still
return the output from pam_nologin to the client.
$Id: README.platform,v 1.10 2009/08/28 23:14:48 dtucker Exp $

View File

@@ -0,0 +1,63 @@
Privilege separation, or privsep, is method in OpenSSH by which
operations that require root privilege are performed by a separate
privileged monitor process. Its purpose is to prevent privilege
escalation by containing corruption to an unprivileged process.
More information is available at:
http://www.citi.umich.edu/u/provos/ssh/privsep.html
Privilege separation is now enabled by default; see the
UsePrivilegeSeparation option in sshd_config(5).
On systems which lack mmap or anonymous (MAP_ANON) memory mapping,
compression must be disabled in order for privilege separation to
function.
When privsep is enabled, during the pre-authentication phase sshd will
chroot(2) to "/var/empty" and change its privileges to the "sshd" user
and its primary group. sshd is a pseudo-account that should not be
used by other daemons, and must be locked and should contain a
"nologin" or invalid shell.
You should do something like the following to prepare the privsep
preauth environment:
# mkdir /var/empty
# chown root:sys /var/empty
# chmod 755 /var/empty
# groupadd sshd
# useradd -g sshd -c 'sshd privsep' -d /var/empty -s /bin/false sshd
/var/empty should not contain any files.
configure supports the following options to change the default
privsep user and chroot directory:
--with-privsep-path=xxx Path for privilege separation chroot
--with-privsep-user=user Specify non-privileged user for privilege separation
Privsep requires operating system support for file descriptor passing.
Compression will be disabled on systems without a working mmap MAP_ANON.
PAM-enabled OpenSSH is known to function with privsep on AIX, FreeBSD,
HP-UX (including Trusted Mode), Linux, NetBSD and Solaris.
On Cygwin, Tru64 Unix, OpenServer, and Unicos only the pre-authentication
part of privsep is supported. Post-authentication privsep is disabled
automatically (so you won't see the additional process mentioned below).
Note that for a normal interactive login with a shell, enabling privsep
will require 1 additional process per login session.
Given the following process listing (from HP-UX):
UID PID PPID C STIME TTY TIME COMMAND
root 1005 1 0 10:45:17 ? 0:08 /opt/openssh/sbin/sshd -u0
root 6917 1005 0 15:19:16 ? 0:00 sshd: stevesk [priv]
stevesk 6919 6917 0 15:19:17 ? 0:03 sshd: stevesk@2
stevesk 6921 6919 0 15:19:17 pts/2 0:00 -bash
process 1005 is the sshd process listening for new connections.
process 6917 is the privileged monitor process, 6919 is the user owned
sshd process and 6921 is the shell process.
$Id: README.privsep,v 1.16 2005/06/04 23:21:41 djm Exp $

View File

@@ -0,0 +1,132 @@
How to use OpenSSH-based virtual private networks
-------------------------------------------------
OpenSSH contains support for VPN tunneling using the tun(4) network
tunnel pseudo-device which is available on most platforms, either for
layer 2 or 3 traffic.
The following brief instructions on how to use this feature use
a network configuration specific to the OpenBSD operating system.
(1) Server: Enable support for SSH tunneling
To enable the ssh server to accept tunnel requests from the client, you
have to add the following option to the ssh server configuration file
(/etc/ssh/sshd_config):
PermitTunnel yes
Restart the server or send the hangup signal (SIGHUP) to let the server
reread it's configuration.
(2) Server: Restrict client access and assign the tunnel
The OpenSSH server simply uses the file /root/.ssh/authorized_keys to
restrict the client to connect to a specified tunnel and to
automatically start the related interface configuration command. These
settings are optional but recommended:
tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... reyk@openbsd.org
(3) Client: Configure the local network tunnel interface
Use the hostname.if(5) interface-specific configuration file to set up
the network tunnel configuration with OpenBSD. For example, use the
following configuration in /etc/hostname.tun0 to set up the layer 3
tunnel on the client:
inet 192.168.5.1 255.255.255.252 192.168.5.2
OpenBSD also supports layer 2 tunneling over the tun device by adding
the link0 flag:
inet 192.168.1.78 255.255.255.0 192.168.1.255 link0
Layer 2 tunnels can be used in combination with an Ethernet bridge(4)
interface, like the following example for /etc/bridgename.bridge0:
add tun0
add sis0
up
(4) Client: Configure the OpenSSH client
To establish tunnel forwarding for connections to a specified
remote host by default, use the following ssh client configuration for
the privileged user (in /root/.ssh/config):
Host sshgateway
Tunnel yes
TunnelDevice 0:any
PermitLocalCommand yes
LocalCommand sh /etc/netstart tun0
A more complicated configuration is possible to establish a tunnel to
a remote host which is not directly accessible by the client.
The following example describes a client configuration to connect to
the remote host over two ssh hops in between. It uses the OpenSSH
ProxyCommand in combination with the nc(1) program to forward the final
ssh tunnel destination over multiple ssh sessions.
Host access.somewhere.net
User puffy
Host dmzgw
User puffy
ProxyCommand ssh access.somewhere.net nc dmzgw 22
Host sshgateway
Tunnel Ethernet
TunnelDevice 0:any
PermitLocalCommand yes
LocalCommand sh /etc/netstart tun0
ProxyCommand ssh dmzgw nc sshgateway 22
The following network plan illustrates the previous configuration in
combination with layer 2 tunneling and Ethernet bridging.
+--------+ ( ) +----------------------+
| Client |------( Internet )-----| access.somewhere.net |
+--------+ ( ) +----------------------+
: 192.168.1.78 |
:............................. +-------+
Forwarded ssh connection : | dmzgw |
Layer 2 tunnel : +-------+
: |
: |
: +------------+
:......| sshgateway |
| +------------+
--- real connection Bridge -> | +----------+
... "virtual connection" [ X ]--------| somehost |
[X] switch +----------+
192.168.1.25
(5) Client: Connect to the server and establish the tunnel
Finally connect to the OpenSSH server to establish the tunnel by using
the following command:
ssh sshgateway
It is also possible to tell the client to fork into the background after
the connection has been successfully established:
ssh -f sshgateway true
Without the ssh configuration done in step (4), it is also possible
to use the following command lines:
ssh -fw 0:1 sshgateway true
ifconfig tun0 192.168.5.1 192.168.5.2 netmask 255.255.255.252
Using OpenSSH tunnel forwarding is a simple way to establish secure
and ad hoc virtual private networks. Possible fields of application
could be wireless networks or administrative VPN tunnels.
Nevertheless, ssh tunneling requires some packet header overhead and
runs on top of TCP. It is still suggested to use the IP Security
Protocol (IPSec) for robust and permanent VPN connections and to
interconnect corporate networks.
Reyk Floeter
$OpenBSD: README.tun,v 1.4 2006/03/28 00:12:31 deraadt Exp $

86
crypto/external/bsd/openssh/dist/TODO vendored Normal file
View File

@@ -0,0 +1,86 @@
Documentation:
- Update the docs
- Update README
- Update INSTALL
- Merge INSTALL & README.privsep
- Install FAQ?
- General FAQ on S/Key, TIS, RSA, RSA2, DSA, etc and suggestions on when it
would be best to use them.
- Create a Documentation/ directory?
Programming:
- Grep for 'XXX' comments and fix
- Link order is incorrect for some systems using Kerberos 4 and AFS. Result
is multiple inclusion of DES symbols. Holger Trapp
<holger.trapp@hrz.tu-chemnitz.de> reports that changing the configure
generated link order from:
-lresolv -lkrb -lz -lnsl -lutil -lkafs -lkrb -ldes -lcrypto
to:
-lresolv -lkrb -lz -lnsl -lutil -lcrypto -lkafs -lkrb -ldes
fixing the problem.
- Write a test program that calls stat() to search for EGD/PRNGd socket
rather than use the (non-portable) "test -S".
- More platforms for for setproctitle() emulation (testing needed)
- Improve PAM ChallengeResponseAuthentication
- Informational messages
- Use different PAM service name for kbdint vs regular auth (suggest from
Solar Designer)
- Ability to select which ChallengeResponseAuthentications may be used
and order to try them in e.g. "ChallengeResponseAuthentication skey, pam"
- Complete Tru64 SIA support
- It looks like we could merge it into the password auth code to cut down
on diff size. Maybe PAM password auth too?
- Finish integrating kernel-level auditing code for IRIX and SOLARIS
(Gilbert.r.loomis@saic.com)
- 64-bit builds on HP-UX 11.X (stevesk@pobox.com):
- utmp/wtmp get corrupted (something in loginrec?)
- can't build with PAM (no 64-bit libpam yet)
Clean up configure/makefiles:
- Clean up configure.ac - There are a few double #defined variables
left to do. HAVE_LOGIN is one of them. Consider NOT looking for
information in wtmpx or utmpx or any of that stuff if it's not detected
from the start
- Replace the whole u_intXX_t evilness in acconfig.h with something better???
- Do it in configure.ac
- Consider splitting the u_intXX_t test for sys/bitype.h into seperate test
to allow people to (right/wrongfully) link against Bind directly.
- Consider splitting configure.ac into seperate files which do logically
similar tests. E.g move all the type detection stuff into one file,
entropy related stuff into another.
Packaging:
- HP-UX: Provide DEPOT package scripts.
(gilbert.r.loomis@saic.com)
PrivSep Issues:
- mmap() issues.
+ /dev/zero solution (Solaris)
+ No/broken MAP_ANON (Irix)
+ broken /dev/zero parse (Linux)
- PAM
+ See above PAM notes
- AIX
+ usrinfo() does not set TTY, but only required for legacy systems. Works
with PrivSep.
- OSF
+ SIA is broken
- Cygwin
+ Privsep for Pre-auth only (no fd passing)
$Id: TODO,v 1.58 2004/12/06 11:40:11 dtucker Exp $

View File

@@ -0,0 +1,499 @@
/* $OpenBSD: addrmatch.c,v 1.10 2015/07/08 19:04:21 markus Exp $ */
/*
* Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "match.h"
#include "log.h"
struct xaddr {
sa_family_t af;
union {
struct in_addr v4;
struct in6_addr v6;
u_int8_t addr8[16];
u_int32_t addr32[4];
} xa; /* 128-bit address */
u_int32_t scope_id; /* iface scope id for v6 */
#define v4 xa.v4
#define v6 xa.v6
#define addr8 xa.addr8
#define addr32 xa.addr32
};
static int
addr_unicast_masklen(int af)
{
switch (af) {
case AF_INET:
return 32;
case AF_INET6:
return 128;
default:
return -1;
}
}
static inline int
masklen_valid(int af, u_int masklen)
{
switch (af) {
case AF_INET:
return masklen <= 32 ? 0 : -1;
case AF_INET6:
return masklen <= 128 ? 0 : -1;
default:
return -1;
}
}
/*
* Convert struct sockaddr to struct xaddr
* Returns 0 on success, -1 on failure.
*/
static int
addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
{
struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
memset(xa, '\0', sizeof(*xa));
switch (sa->sa_family) {
case AF_INET:
if (slen < (socklen_t)sizeof(*in4))
return -1;
xa->af = AF_INET;
memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
break;
case AF_INET6:
if (slen < (socklen_t)sizeof(*in6))
return -1;
xa->af = AF_INET6;
memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
xa->scope_id = in6->sin6_scope_id;
#endif
break;
default:
return -1;
}
return 0;
}
/*
* Calculate a netmask of length 'l' for address family 'af' and
* store it in 'n'.
* Returns 0 on success, -1 on failure.
*/
static int
addr_netmask(int af, u_int l, struct xaddr *n)
{
int i;
if (masklen_valid(af, l) != 0 || n == NULL)
return -1;
memset(n, '\0', sizeof(*n));
switch (af) {
case AF_INET:
n->af = AF_INET;
if (l == 0)
return 0;
n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
return 0;
case AF_INET6:
n->af = AF_INET6;
for (i = 0; i < 4 && l >= 32; i++, l -= 32)
n->addr32[i] = 0xffffffffU;
if (i < 4 && l != 0)
n->addr32[i] = htonl((0xffffffff << (32 - l)) &
0xffffffff);
return 0;
default:
return -1;
}
}
/*
* Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
* Returns 0 on success, -1 on failure.
*/
static int
addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
{
int i;
if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
return -1;
memcpy(dst, a, sizeof(*dst));
switch (a->af) {
case AF_INET:
dst->v4.s_addr &= b->v4.s_addr;
return 0;
case AF_INET6:
dst->scope_id = a->scope_id;
for (i = 0; i < 4; i++)
dst->addr32[i] &= b->addr32[i];
return 0;
default:
return -1;
}
}
/*
* Compare addresses 'a' and 'b'
* Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b)
*/
static int
addr_cmp(const struct xaddr *a, const struct xaddr *b)
{
int i;
if (a->af != b->af)
return a->af == AF_INET6 ? 1 : -1;
switch (a->af) {
case AF_INET:
if (a->v4.s_addr == b->v4.s_addr)
return 0;
return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1;
case AF_INET6:
for (i = 0; i < 16; i++)
if (a->addr8[i] - b->addr8[i] != 0)
return a->addr8[i] > b->addr8[i] ? 1 : -1;
if (a->scope_id == b->scope_id)
return 0;
return a->scope_id > b->scope_id ? 1 : -1;
default:
return -1;
}
}
/*
* Parse string address 'p' into 'n'
* Returns 0 on success, -1 on failure.
*/
static int
addr_pton(const char *p, struct xaddr *n)
{
struct addrinfo hints, *ai;
memset(&hints, '\0', sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
return -1;
if (ai == NULL || ai->ai_addr == NULL)
return -1;
if (n != NULL &&
addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) {
freeaddrinfo(ai);
return -1;
}
freeaddrinfo(ai);
return 0;
}
/*
* Perform bitwise negation of address
* Returns 0 on success, -1 on failure.
*/
static int
addr_invert(struct xaddr *n)
{
int i;
if (n == NULL)
return (-1);
switch (n->af) {
case AF_INET:
n->v4.s_addr = ~n->v4.s_addr;
return (0);
case AF_INET6:
for (i = 0; i < 4; i++)
n->addr32[i] = ~n->addr32[i];
return (0);
default:
return (-1);
}
}
/*
* Calculate a netmask of length 'l' for address family 'af' and
* store it in 'n'.
* Returns 0 on success, -1 on failure.
*/
static int
addr_hostmask(int af, u_int l, struct xaddr *n)
{
if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
return (-1);
return (0);
}
/*
* Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::)
* Returns 0 on if address is all-zeros, -1 if not all zeros or on failure.
*/
static int
addr_is_all0s(const struct xaddr *a)
{
int i;
switch (a->af) {
case AF_INET:
return (a->v4.s_addr == 0 ? 0 : -1);
case AF_INET6:;
for (i = 0; i < 4; i++)
if (a->addr32[i] != 0)
return (-1);
return (0);
default:
return (-1);
}
}
/*
* Test whether host portion of address 'a', as determined by 'masklen'
* is all zeros.
* Returns 0 on if host portion of address is all-zeros,
* -1 if not all zeros or on failure.
*/
static int
addr_host_is_all0s(const struct xaddr *a, u_int masklen)
{
struct xaddr tmp_addr, tmp_mask, tmp_result;
memcpy(&tmp_addr, a, sizeof(tmp_addr));
if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
return (-1);
if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
return (-1);
return (addr_is_all0s(&tmp_result));
}
/*
* Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
* Return -1 on parse error, -2 on inconsistency or 0 on success.
*/
static int
addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
{
struct xaddr tmp;
long unsigned int masklen = 999;
char addrbuf[64], *mp, *cp;
/* Don't modify argument */
if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
return -1;
if ((mp = strchr(addrbuf, '/')) != NULL) {
*mp = '\0';
mp++;
masklen = strtoul(mp, &cp, 10);
if (*mp == '\0' || *cp != '\0' || masklen > 128)
return -1;
}
if (addr_pton(addrbuf, &tmp) == -1)
return -1;
if (mp == NULL)
masklen = addr_unicast_masklen(tmp.af);
if (masklen_valid(tmp.af, masklen) == -1)
return -2;
if (addr_host_is_all0s(&tmp, masklen) != 0)
return -2;
if (n != NULL)
memcpy(n, &tmp, sizeof(*n));
if (l != NULL)
*l = masklen;
return 0;
}
static int
addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
{
struct xaddr tmp_mask, tmp_result;
if (host->af != net->af)
return -1;
if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
return -1;
if (addr_and(&tmp_result, host, &tmp_mask) == -1)
return -1;
return addr_cmp(&tmp_result, net);
}
/*
* Match "addr" against list pattern list "_list", which may contain a
* mix of CIDR addresses and old-school wildcards.
*
* If addr is NULL, then no matching is performed, but _list is parsed
* and checked for well-formedness.
*
* Returns 1 on match found (never returned when addr == NULL).
* Returns 0 on if no match found, or no errors found when addr == NULL.
* Returns -1 on negated match found (never returned when addr == NULL).
* Returns -2 on invalid list entry.
*/
int
addr_match_list(const char *addr, const char *_list)
{
char *list, *cp, *o;
struct xaddr try_addr, match_addr;
u_int masklen, neg;
int ret = 0, r;
if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
debug2("%s: couldn't parse address %.100s", __func__, addr);
return 0;
}
if ((o = list = strdup(_list)) == NULL)
return -1;
while ((cp = strsep(&list, ",")) != NULL) {
neg = *cp == '!';
if (neg)
cp++;
if (*cp == '\0') {
ret = -2;
break;
}
/* Prefer CIDR address matching */
r = addr_pton_cidr(cp, &match_addr, &masklen);
if (r == -2) {
error("Inconsistent mask length for "
"network \"%.100s\"", cp);
ret = -2;
break;
} else if (r == 0) {
if (addr != NULL && addr_netmatch(&try_addr,
&match_addr, masklen) == 0) {
foundit:
if (neg) {
ret = -1;
break;
}
ret = 1;
}
continue;
} else {
/* If CIDR parse failed, try wildcard string match */
if (addr != NULL && match_pattern(addr, cp) == 1)
goto foundit;
}
}
free(o);
return ret;
}
/*
* Match "addr" against list CIDR list "_list". Lexical wildcards and
* negation are not supported. If "addr" == NULL, will verify structure
* of "_list".
*
* Returns 1 on match found (never returned when addr == NULL).
* Returns 0 on if no match found, or no errors found when addr == NULL.
* Returns -1 on error
*/
int
addr_match_cidr_list(const char *addr, const char *_list)
{
char *list, *cp, *o;
struct xaddr try_addr, match_addr;
u_int masklen;
int ret = 0, r;
if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
debug2("%s: couldn't parse address %.100s", __func__, addr);
return 0;
}
if ((o = list = strdup(_list)) == NULL)
return -1;
while ((cp = strsep(&list, ",")) != NULL) {
if (*cp == '\0') {
error("%s: empty entry in list \"%.100s\"",
__func__, o);
ret = -1;
break;
}
/*
* NB. This function is called in pre-auth with untrusted data,
* so be extra paranoid about junk reaching getaddrino (via
* addr_pton_cidr).
*/
/* Stop junk from reaching getaddrinfo. +3 is for masklen */
if (strlen(cp) > INET6_ADDRSTRLEN + 3) {
error("%s: list entry \"%.100s\" too long",
__func__, cp);
ret = -1;
break;
}
#define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/"
if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) {
error("%s: list entry \"%.100s\" contains invalid "
"characters", __func__, cp);
ret = -1;
}
/* Prefer CIDR address matching */
r = addr_pton_cidr(cp, &match_addr, &masklen);
if (r == -1) {
error("Invalid network entry \"%.100s\"", cp);
ret = -1;
break;
} else if (r == -2) {
error("Inconsistent mask length for "
"network \"%.100s\"", cp);
ret = -1;
break;
} else if (r == 0 && addr != NULL) {
if (addr_netmatch(&try_addr, &match_addr,
masklen) == 0)
ret = 1;
continue;
}
}
free(o);
return ret;
}

View File

@@ -0,0 +1,170 @@
/* $OpenBSD: atomicio.c,v 1.27 2015/01/16 06:40:12 deraadt Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/param.h>
#include <sys/uio.h>
#include <errno.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
#endif
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "atomicio.h"
/*
* ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
int (*cb)(void *, size_t), void *cb_arg)
{
char *s = _s;
size_t pos = 0;
ssize_t res;
struct pollfd pfd;
#ifndef BROKEN_READ_COMPARISON
pfd.fd = fd;
pfd.events = f == read ? POLLIN : POLLOUT;
#endif
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR)
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
#ifndef BROKEN_READ_COMPARISON
(void)poll(&pfd, 1, -1);
#endif
continue;
}
return 0;
case 0:
errno = EPIPE;
return pos;
default:
pos += (size_t)res;
if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
errno = EINTR;
return pos;
}
}
}
return pos;
}
size_t
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
{
return atomicio6(f, fd, _s, n, NULL, NULL);
}
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt,
int (*cb)(void *, size_t), void *cb_arg)
{
size_t pos = 0, rem;
ssize_t res;
struct iovec iov_array[IOV_MAX], *iov = iov_array;
struct pollfd pfd;
if (iovcnt > IOV_MAX) {
errno = EINVAL;
return 0;
}
/* Make a copy of the iov array because we may modify it below */
memcpy(iov, _iov, iovcnt * sizeof(*_iov));
#ifndef BROKEN_READV_COMPARISON
pfd.fd = fd;
pfd.events = f == readv ? POLLIN : POLLOUT;
#endif
for (; iovcnt > 0 && iov[0].iov_len > 0;) {
res = (f) (fd, iov, iovcnt);
switch (res) {
case -1:
if (errno == EINTR)
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
#ifndef BROKEN_READV_COMPARISON
(void)poll(&pfd, 1, -1);
#endif
continue;
}
return 0;
case 0:
errno = EPIPE;
return pos;
default:
rem = (size_t)res;
pos += rem;
/* skip completed iov entries */
while (iovcnt > 0 && rem >= iov[0].iov_len) {
rem -= iov[0].iov_len;
iov++;
iovcnt--;
}
/* This shouldn't happen... */
if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
errno = EFAULT;
return 0;
}
if (iovcnt == 0)
break;
/* update pointer in partially complete iov */
iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
iov[0].iov_len -= rem;
}
if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
errno = EINTR;
return pos;
}
}
return pos;
}
size_t
atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt)
{
return atomiciov6(f, fd, _iov, iovcnt, NULL, NULL);
}

View File

@@ -0,0 +1,51 @@
/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ATOMICIO_H
#define _ATOMICIO_H
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
int (*cb)(void *, size_t), void *);
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt, int (*cb)(void *, size_t), void *);
size_t atomiciov(ssize_t (*)(int, const struct iovec *, int),
int, const struct iovec *, int);
#endif /* _ATOMICIO_H */

View File

@@ -0,0 +1,457 @@
/* $Id: audit-bsm.c,v 1.8 2012/02/23 23:40:43 dtucker Exp $ */
/*
* TODO
*
* - deal with overlap between this and sys_auth_allowed_user
* sys_auth_record_login and record_failed_login.
*/
/*
* Copyright 1988-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* #pragma ident "@(#)bsmaudit.c 1.1 01/09/17 SMI" */
#include "includes.h"
#if defined(USE_BSM_AUDIT)
#include <sys/types.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#ifdef BROKEN_BSM_API
#include <libscf.h>
#endif
#include "ssh.h"
#include "log.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "xmalloc.h"
#ifndef AUE_openssh
# define AUE_openssh 32800
#endif
#include <bsm/audit.h>
#include <bsm/libbsm.h>
#include <bsm/audit_uevents.h>
#include <bsm/audit_record.h>
#include <locale.h>
#if defined(HAVE_GETAUDIT_ADDR)
#define AuditInfoStruct auditinfo_addr
#define AuditInfoTermID au_tid_addr_t
#define SetAuditFunc(a,b) setaudit_addr((a),(b))
#define SetAuditFuncText "setaudit_addr"
#define AUToSubjectFunc au_to_subject_ex
#define AUToReturnFunc(a,b) au_to_return32((a), (int32_t)(b))
#else
#define AuditInfoStruct auditinfo
#define AuditInfoTermID au_tid_t
#define SetAuditFunc(a,b) setaudit(a)
#define SetAuditFuncText "setaudit"
#define AUToSubjectFunc au_to_subject
#define AUToReturnFunc(a,b) au_to_return((a), (u_int)(b))
#endif
#ifndef cannot_audit
extern int cannot_audit(int);
#endif
extern void aug_init(void);
extern void aug_save_auid(au_id_t);
extern void aug_save_uid(uid_t);
extern void aug_save_euid(uid_t);
extern void aug_save_gid(gid_t);
extern void aug_save_egid(gid_t);
extern void aug_save_pid(pid_t);
extern void aug_save_asid(au_asid_t);
extern void aug_save_tid(dev_t, unsigned int);
extern void aug_save_tid_ex(dev_t, u_int32_t *, u_int32_t);
extern int aug_save_me(void);
extern int aug_save_namask(void);
extern void aug_save_event(au_event_t);
extern void aug_save_sorf(int);
extern void aug_save_text(char *);
extern void aug_save_text1(char *);
extern void aug_save_text2(char *);
extern void aug_save_na(int);
extern void aug_save_user(char *);
extern void aug_save_path(char *);
extern int aug_save_policy(void);
extern void aug_save_afunc(int (*)(int));
extern int aug_audit(void);
extern int aug_na_selected(void);
extern int aug_selected(void);
extern int aug_daemon_session(void);
#ifndef HAVE_GETTEXT
# define gettext(a) (a)
#endif
extern Authctxt *the_authctxt;
static AuditInfoTermID ssh_bsm_tid;
#ifdef BROKEN_BSM_API
/* For some reason this constant is no longer defined
in Solaris 11. */
#define BSM_TEXTBUFSZ 256
#endif
/* Below is the low-level BSM interface code */
/*
* aug_get_machine is only required on IPv6 capable machines, we use a
* different mechanism in audit_connection_from() for IPv4-only machines.
* getaudit_addr() is only present on IPv6 capable machines.
*/
#if defined(HAVE_AUG_GET_MACHINE) || !defined(HAVE_GETAUDIT_ADDR)
extern int aug_get_machine(char *, u_int32_t *, u_int32_t *);
#else
static int
aug_get_machine(char *host, u_int32_t *addr, u_int32_t *type)
{
struct addrinfo *ai;
struct sockaddr_in *in4;
struct sockaddr_in6 *in6;
int ret = 0, r;
if ((r = getaddrinfo(host, NULL, NULL, &ai)) != 0) {
error("BSM audit: getaddrinfo failed for %.100s: %.100s", host,
r == EAI_SYSTEM ? strerror(errno) : gai_strerror(r));
return -1;
}
switch (ai->ai_family) {
case AF_INET:
in4 = (struct sockaddr_in *)ai->ai_addr;
*type = AU_IPv4;
memcpy(addr, &in4->sin_addr, sizeof(struct in_addr));
break;
#ifdef AU_IPv6
case AF_INET6:
in6 = (struct sockaddr_in6 *)ai->ai_addr;
*type = AU_IPv6;
memcpy(addr, &in6->sin6_addr, sizeof(struct in6_addr));
break;
#endif
default:
error("BSM audit: unknown address family for %.100s: %d",
host, ai->ai_family);
ret = -1;
}
freeaddrinfo(ai);
return ret;
}
#endif
#ifdef BROKEN_BSM_API
/*
In Solaris 11 the audit daemon has been moved to SMF. In the process
they simply dropped getacna() from the API, since it read from a now
non-existent config file. This function re-implements getacna() to
read from the SMF repository instead.
*/
int
getacna(char *auditstring, int len)
{
scf_handle_t *handle = NULL;
scf_property_t *property = NULL;
scf_value_t *value = NULL;
int ret = 0;
handle = scf_handle_create(SCF_VERSION);
if (handle == NULL)
return -2; /* The man page for getacna on Solaris 10 states
we should return -2 in case of error and set
errno to indicate the error. We don't bother
with errno here, though, since the only use
of this function below doesn't check for errors
anyway.
*/
ret = scf_handle_bind(handle);
if (ret == -1)
return -2;
property = scf_property_create(handle);
if (property == NULL)
return -2;
ret = scf_handle_decode_fmri(handle,
"svc:/system/auditd:default/:properties/preselection/naflags",
NULL, NULL, NULL, NULL, property, 0);
if (ret == -1)
return -2;
value = scf_value_create(handle);
if (value == NULL)
return -2;
ret = scf_property_get_value(property, value);
if (ret == -1)
return -2;
ret = scf_value_get_astring(value, auditstring, len);
if (ret == -1)
return -2;
scf_value_destroy(value);
scf_property_destroy(property);
scf_handle_destroy(handle);
return 0;
}
#endif
/*
* Check if the specified event is selected (enabled) for auditing.
* Returns 1 if the event is selected, 0 if not and -1 on failure.
*/
static int
selected(char *username, uid_t uid, au_event_t event, int sf)
{
int rc, sorf;
char naflags[512];
struct au_mask mask;
mask.am_success = mask.am_failure = 0;
if (uid < 0) {
/* get flags for non-attributable (to a real user) events */
rc = getacna(naflags, sizeof(naflags));
if (rc == 0)
(void) getauditflagsbin(naflags, &mask);
} else
rc = au_user_mask(username, &mask);
sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
return(au_preselect(event, &mask, sorf, AU_PRS_REREAD));
}
static void
bsm_audit_record(int typ, char *string, au_event_t event_no)
{
int ad, rc, sel;
uid_t uid = -1;
gid_t gid = -1;
pid_t pid = getpid();
AuditInfoTermID tid = ssh_bsm_tid;
if (the_authctxt != NULL && the_authctxt->valid) {
uid = the_authctxt->pw->pw_uid;
gid = the_authctxt->pw->pw_gid;
}
rc = (typ == 0) ? 0 : -1;
sel = selected(the_authctxt->user, uid, event_no, rc);
debug3("BSM audit: typ %d rc %d \"%s\"", typ, rc, string);
if (!sel)
return; /* audit event does not match mask, do not write */
debug3("BSM audit: writing audit new record");
ad = au_open();
(void) au_write(ad, AUToSubjectFunc(uid, uid, gid, uid, gid,
pid, pid, &tid));
(void) au_write(ad, au_to_text(string));
(void) au_write(ad, AUToReturnFunc(typ, rc));
#ifdef BROKEN_BSM_API
/* The last argument is the event modifier flags. For
some seemingly undocumented reason it was added in
Solaris 11. */
rc = au_close(ad, AU_TO_WRITE, event_no, 0);
#else
rc = au_close(ad, AU_TO_WRITE, event_no);
#endif
if (rc < 0)
error("BSM audit: %s failed to write \"%s\" record: %s",
__func__, string, strerror(errno));
}
static void
bsm_audit_session_setup(void)
{
int rc;
struct AuditInfoStruct info;
au_mask_t mask;
if (the_authctxt == NULL) {
error("BSM audit: session setup internal error (NULL ctxt)");
return;
}
if (the_authctxt->valid)
info.ai_auid = the_authctxt->pw->pw_uid;
else
info.ai_auid = -1;
info.ai_asid = getpid();
mask.am_success = 0;
mask.am_failure = 0;
(void) au_user_mask(the_authctxt->user, &mask);
info.ai_mask.am_success = mask.am_success;
info.ai_mask.am_failure = mask.am_failure;
info.ai_termid = ssh_bsm_tid;
rc = SetAuditFunc(&info, sizeof(info));
if (rc < 0)
error("BSM audit: %s: %s failed: %s", __func__,
SetAuditFuncText, strerror(errno));
}
static void
bsm_audit_bad_login(const char *what)
{
char textbuf[BSM_TEXTBUFSZ];
if (the_authctxt->valid) {
(void) snprintf(textbuf, sizeof (textbuf),
gettext("invalid %s for user %s"),
what, the_authctxt->user);
bsm_audit_record(4, textbuf, AUE_openssh);
} else {
(void) snprintf(textbuf, sizeof (textbuf),
gettext("invalid user name \"%s\""),
the_authctxt->user);
bsm_audit_record(3, textbuf, AUE_openssh);
}
}
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
AuditInfoTermID *tid = &ssh_bsm_tid;
char buf[1024];
if (cannot_audit(0))
return;
debug3("BSM audit: connection from %.100s port %d", host, port);
/* populate our terminal id structure */
#if defined(HAVE_GETAUDIT_ADDR)
tid->at_port = (dev_t)port;
aug_get_machine((char *)host, &(tid->at_addr[0]), &(tid->at_type));
snprintf(buf, sizeof(buf), "%08x %08x %08x %08x", tid->at_addr[0],
tid->at_addr[1], tid->at_addr[2], tid->at_addr[3]);
debug3("BSM audit: iptype %d machine ID %s", (int)tid->at_type, buf);
#else
/* this is used on IPv4-only machines */
tid->port = (dev_t)port;
tid->machine = inet_addr(host);
snprintf(buf, sizeof(buf), "%08x", tid->machine);
debug3("BSM audit: machine ID %s", buf);
#endif
}
void
audit_run_command(const char *command)
{
/* not implemented */
}
void
audit_session_open(struct logininfo *li)
{
/* not implemented */
}
void
audit_session_close(struct logininfo *li)
{
/* not implemented */
}
void
audit_event(ssh_audit_event_t event)
{
char textbuf[BSM_TEXTBUFSZ];
static int logged_in = 0;
const char *user = the_authctxt ? the_authctxt->user : "(unknown user)";
if (cannot_audit(0))
return;
switch(event) {
case SSH_AUTH_SUCCESS:
logged_in = 1;
bsm_audit_session_setup();
snprintf(textbuf, sizeof(textbuf),
gettext("successful login %s"), user);
bsm_audit_record(0, textbuf, AUE_openssh);
break;
case SSH_CONNECTION_CLOSE:
/*
* We can also get a close event if the user attempted auth
* but never succeeded.
*/
if (logged_in) {
snprintf(textbuf, sizeof(textbuf),
gettext("sshd logout %s"), the_authctxt->user);
bsm_audit_record(0, textbuf, AUE_logout);
} else {
debug("%s: connection closed without authentication",
__func__);
}
break;
case SSH_NOLOGIN:
bsm_audit_record(1,
gettext("logins disabled by /etc/nologin"), AUE_openssh);
break;
case SSH_LOGIN_EXCEED_MAXTRIES:
snprintf(textbuf, sizeof(textbuf),
gettext("too many tries for user %s"), the_authctxt->user);
bsm_audit_record(1, textbuf, AUE_openssh);
break;
case SSH_LOGIN_ROOT_DENIED:
bsm_audit_record(2, gettext("not_console"), AUE_openssh);
break;
case SSH_AUTH_FAIL_PASSWD:
bsm_audit_bad_login("password");
break;
case SSH_AUTH_FAIL_KBDINT:
bsm_audit_bad_login("interactive password entry");
break;
default:
debug("%s: unhandled event %d", __func__, event);
}
}
#endif /* BSM */

View File

@@ -0,0 +1,126 @@
/* $Id: audit-linux.c,v 1.1 2011/01/17 10:15:30 dtucker Exp $ */
/*
* Copyright 2010 Red Hat, Inc. All rights reserved.
* Use is subject to license terms.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Red Hat author: Jan F. Chadima <jchadima@redhat.com>
*/
#include "includes.h"
#if defined(USE_LINUX_AUDIT)
#include <libaudit.h>
#include <unistd.h>
#include <string.h>
#include "log.h"
#include "audit.h"
#include "canohost.h"
const char* audit_username(void);
int
linux_audit_record_event(int uid, const char *username,
const char *hostname, const char *ip, const char *ttyn, int success)
{
int audit_fd, rc, saved_errno;
audit_fd = audit_open();
if (audit_fd < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
return 1; /* No audit support in kernel */
else
return 0; /* Must prevent login */
}
rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
NULL, "login", username ? username : "(unknown)",
username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
close(audit_fd);
/*
* Do not report error if the error is EPERM and sshd is run as non
* root user.
*/
if ((rc == -EPERM) && (geteuid() != 0))
rc = 0;
errno = saved_errno;
return (rc >= 0);
}
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
}
/* not implemented */
void
audit_run_command(const char *command)
{
/* not implemented */
}
void
audit_session_open(struct logininfo *li)
{
if (linux_audit_record_event(li->uid, NULL, li->hostname,
NULL, li->line, 1) == 0)
fatal("linux_audit_write_entry failed: %s", strerror(errno));
}
void
audit_session_close(struct logininfo *li)
{
/* not implemented */
}
void
audit_event(ssh_audit_event_t event)
{
switch(event) {
case SSH_AUTH_SUCCESS:
case SSH_CONNECTION_CLOSE:
case SSH_NOLOGIN:
case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
break;
case SSH_AUTH_FAIL_NONE:
case SSH_AUTH_FAIL_PASSWD:
case SSH_AUTH_FAIL_KBDINT:
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
case SSH_AUTH_FAIL_GSSAPI:
case SSH_INVALID_USER:
linux_audit_record_event(-1, audit_username(), NULL,
get_remote_ipaddr(), "sshd", 0);
break;
default:
debug("%s: unhandled event %d", __func__, event);
}
}
#endif /* USE_LINUX_AUDIT */

186
crypto/external/bsd/openssh/dist/audit.c vendored Normal file
View File

@@ -0,0 +1,186 @@
/* $Id: audit.c,v 1.6 2011/01/17 10:15:30 dtucker Exp $ */
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <stdarg.h>
#include <string.h>
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
#include "log.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
/*
* Care must be taken when using this since it WILL NOT be initialized when
* audit_connection_from() is called and MAY NOT be initialized when
* audit_event(CONNECTION_ABANDON) is called. Test for NULL before using.
*/
extern Authctxt *the_authctxt;
/* Maybe add the audit class to struct Authmethod? */
ssh_audit_event_t
audit_classify_auth(const char *method)
{
if (strcmp(method, "none") == 0)
return SSH_AUTH_FAIL_NONE;
else if (strcmp(method, "password") == 0)
return SSH_AUTH_FAIL_PASSWD;
else if (strcmp(method, "publickey") == 0 ||
strcmp(method, "rsa") == 0)
return SSH_AUTH_FAIL_PUBKEY;
else if (strncmp(method, "keyboard-interactive", 20) == 0 ||
strcmp(method, "challenge-response") == 0)
return SSH_AUTH_FAIL_KBDINT;
else if (strcmp(method, "hostbased") == 0 ||
strcmp(method, "rhosts-rsa") == 0)
return SSH_AUTH_FAIL_HOSTBASED;
else if (strcmp(method, "gssapi-with-mic") == 0)
return SSH_AUTH_FAIL_GSSAPI;
else
return SSH_AUDIT_UNKNOWN;
}
/* helper to return supplied username */
const char *
audit_username(void)
{
static const char unknownuser[] = "(unknown user)";
static const char invaliduser[] = "(invalid user)";
if (the_authctxt == NULL || the_authctxt->user == NULL)
return (unknownuser);
if (!the_authctxt->valid)
return (invaliduser);
return (the_authctxt->user);
}
const char *
audit_event_lookup(ssh_audit_event_t ev)
{
int i;
static struct event_lookup_struct {
ssh_audit_event_t event;
const char *name;
} event_lookup[] = {
{SSH_LOGIN_EXCEED_MAXTRIES, "LOGIN_EXCEED_MAXTRIES"},
{SSH_LOGIN_ROOT_DENIED, "LOGIN_ROOT_DENIED"},
{SSH_AUTH_SUCCESS, "AUTH_SUCCESS"},
{SSH_AUTH_FAIL_NONE, "AUTH_FAIL_NONE"},
{SSH_AUTH_FAIL_PASSWD, "AUTH_FAIL_PASSWD"},
{SSH_AUTH_FAIL_KBDINT, "AUTH_FAIL_KBDINT"},
{SSH_AUTH_FAIL_PUBKEY, "AUTH_FAIL_PUBKEY"},
{SSH_AUTH_FAIL_HOSTBASED, "AUTH_FAIL_HOSTBASED"},
{SSH_AUTH_FAIL_GSSAPI, "AUTH_FAIL_GSSAPI"},
{SSH_INVALID_USER, "INVALID_USER"},
{SSH_NOLOGIN, "NOLOGIN"},
{SSH_CONNECTION_CLOSE, "CONNECTION_CLOSE"},
{SSH_CONNECTION_ABANDON, "CONNECTION_ABANDON"},
{SSH_AUDIT_UNKNOWN, "AUDIT_UNKNOWN"}
};
for (i = 0; event_lookup[i].event != SSH_AUDIT_UNKNOWN; i++)
if (event_lookup[i].event == ev)
break;
return(event_lookup[i].name);
}
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
* These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled.
*/
/*
* Called after a connection has been accepted but before any authentication
* has been attempted.
*/
void
audit_connection_from(const char *host, int port)
{
debug("audit connection from %s port %d euid %d", host, port,
(int)geteuid());
}
/*
* Called when various events occur (see audit.h for a list of possible
* events and what they mean).
*/
void
audit_event(ssh_audit_event_t event)
{
debug("audit event euid %d user %s event %d (%s)", geteuid(),
audit_username(), event, audit_event_lookup(event));
}
/*
* Called when a user session is started. Argument is the tty allocated to
* the session, or NULL if no tty was allocated.
*
* Note that this may be called multiple times if multiple sessions are used
* within a single connection.
*/
void
audit_session_open(struct logininfo *li)
{
const char *t = li->line ? li->line : "(no tty)";
debug("audit session open euid %d user %s tty name %s", geteuid(),
audit_username(), t);
}
/*
* Called when a user session is closed. Argument is the tty allocated to
* the session, or NULL if no tty was allocated.
*
* Note that this may be called multiple times if multiple sessions are used
* within a single connection.
*/
void
audit_session_close(struct logininfo *li)
{
const char *t = li->line ? li->line : "(no tty)";
debug("audit session close euid %d user %s tty name %s", geteuid(),
audit_username(), t);
}
/*
* This will be called when a user runs a non-interactive command. Note that
* it may be called multiple times for a single connection since SSH2 allows
* multiple sessions within a single connection.
*/
void
audit_run_command(const char *command)
{
debug("audit run command euid %d user %s command '%.200s'", geteuid(),
audit_username(), command);
}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */

View File

@@ -0,0 +1,57 @@
/* $Id: audit.h,v 1.4 2011/01/17 10:15:30 dtucker Exp $ */
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SSH_AUDIT_H
# define _SSH_AUDIT_H
#include "loginrec.h"
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
SSH_LOGIN_ROOT_DENIED,
SSH_AUTH_SUCCESS,
SSH_AUTH_FAIL_NONE,
SSH_AUTH_FAIL_PASSWD,
SSH_AUTH_FAIL_KBDINT, /* keyboard-interactive or challenge-response */
SSH_AUTH_FAIL_PUBKEY, /* ssh2 pubkey or ssh1 rsa */
SSH_AUTH_FAIL_HOSTBASED, /* ssh2 hostbased or ssh1 rhostsrsa */
SSH_AUTH_FAIL_GSSAPI,
SSH_INVALID_USER,
SSH_NOLOGIN, /* denied by /etc/nologin, not implemented */
SSH_CONNECTION_CLOSE, /* closed after attempting auth or session */
SSH_CONNECTION_ABANDON, /* closed without completing auth */
SSH_AUDIT_UNKNOWN
};
typedef enum ssh_audit_event_type ssh_audit_event_t;
void audit_connection_from(const char *, int);
void audit_event(ssh_audit_event_t);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
void audit_run_command(const char *);
ssh_audit_event_t audit_classify_auth(const char *);
#endif /* _SSH_AUDIT_H */

View File

@@ -0,0 +1,145 @@
/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef BSD_AUTH
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
#include "buffer.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
static void *
bsdauth_init_ctx(Authctxt *authctxt)
{
return authctxt;
}
int
bsdauth_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
Authctxt *authctxt = ctx;
char *challenge = NULL;
*infotxt = NULL;
*numprompts = 0;
*prompts = NULL;
*echo_on = NULL;
if (authctxt->as != NULL) {
debug2("bsdauth_query: try reuse session");
challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE);
if (challenge == NULL) {
auth_close(authctxt->as);
authctxt->as = NULL;
}
}
if (challenge == NULL) {
debug2("bsdauth_query: new bsd auth session");
debug3("bsdauth_query: style %s",
authctxt->style ? authctxt->style : "<default>");
authctxt->as = auth_userchallenge(authctxt->user,
authctxt->style, "auth-ssh", &challenge);
if (authctxt->as == NULL)
challenge = NULL;
debug2("bsdauth_query: <%s>", challenge ? challenge : "empty");
}
if (challenge == NULL)
return -1;
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xcalloc(*numprompts, sizeof(char *));
*echo_on = xcalloc(*numprompts, sizeof(u_int));
(*prompts)[0] = xstrdup(challenge);
return 0;
}
int
bsdauth_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
int authok;
if (!authctxt->valid)
return -1;
if (authctxt->as == 0)
error("bsdauth_respond: no bsd auth session");
if (numresponses != 1)
return -1;
authok = auth_userresponse(authctxt->as, responses[0], 0);
authctxt->as = NULL;
debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok);
return (authok == 0) ? -1 : 0;
}
static void
bsdauth_free_ctx(void *ctx)
{
Authctxt *authctxt = ctx;
if (authctxt && authctxt->as) {
auth_close(authctxt->as);
authctxt->as = NULL;
}
}
KbdintDevice bsdauth_device = {
"bsdauth",
bsdauth_init_ctx,
bsdauth_query,
bsdauth_respond,
bsdauth_free_ctx
};
KbdintDevice mm_bsdauth_device = {
"bsdauth",
bsdauth_init_ctx,
mm_bsdauth_query,
mm_bsdauth_respond,
bsdauth_free_ctx
};
#endif

View File

@@ -0,0 +1,125 @@
/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
/* limited protocol v1 interface to kbd-interactive authentication */
extern KbdintDevice *devices[];
static KbdintDevice *device;
extern ServerOptions options;
char *
get_challenge(Authctxt *authctxt)
{
char *challenge, *name, *info, **prompts;
u_int i, numprompts;
u_int *echo_on;
#ifdef USE_PAM
if (!options.use_pam)
remove_kbdint_device("pam");
#endif
device = devices[0]; /* we always use the 1st device for protocol 1 */
if (device == NULL)
return NULL;
if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL)
return NULL;
if (device->query(authctxt->kbdintctxt, &name, &info,
&numprompts, &prompts, &echo_on)) {
device->free_ctx(authctxt->kbdintctxt);
authctxt->kbdintctxt = NULL;
return NULL;
}
if (numprompts < 1)
fatal("get_challenge: numprompts < 1");
challenge = xstrdup(prompts[0]);
for (i = 0; i < numprompts; i++)
free(prompts[i]);
free(prompts);
free(name);
free(echo_on);
free(info);
return (challenge);
}
int
verify_response(Authctxt *authctxt, const char *response)
{
char *resp[1], *name, *info, **prompts;
u_int i, numprompts, *echo_on;
int authenticated = 0;
if (device == NULL)
return 0;
if (authctxt->kbdintctxt == NULL)
return 0;
resp[0] = (char *)response;
switch (device->respond(authctxt->kbdintctxt, 1, resp)) {
case 0: /* Success */
authenticated = 1;
break;
case 1: /* Postponed - retry with empty query for PAM */
if ((device->query(authctxt->kbdintctxt, &name, &info,
&numprompts, &prompts, &echo_on)) != 0)
break;
if (numprompts == 0 &&
device->respond(authctxt->kbdintctxt, 0, resp) == 0)
authenticated = 1;
for (i = 0; i < numprompts; i++)
free(prompts[i]);
free(prompts);
free(name);
free(echo_on);
free(info);
break;
}
device->free_ctx(authctxt->kbdintctxt);
authctxt->kbdintctxt = NULL;
return authenticated;
}
void
abandon_challenge_response(Authctxt *authctxt)
{
if (authctxt->kbdintctxt != NULL) {
device->free_ctx(authctxt->kbdintctxt);
authctxt->kbdintctxt = NULL;
}
}

View File

@@ -0,0 +1,273 @@
/* $OpenBSD: auth-krb5.c,v 1.20 2013/07/20 01:55:13 djm Exp $ */
/*
* Kerberos v5 authentication and ticket-passing routines.
*
* $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
*/
/*
* Copyright (c) 2002 Daniel Kouril. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "ssh.h"
#include "ssh1.h"
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "uidswap.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#ifdef KRB5
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <krb5.h>
extern ServerOptions options;
static int
krb5_init(void *context)
{
Authctxt *authctxt = (Authctxt *)context;
krb5_error_code problem;
if (authctxt->krb5_ctx == NULL) {
problem = krb5_init_context(&authctxt->krb5_ctx);
if (problem)
return (problem);
}
return (0);
}
int
auth_krb5_password(Authctxt *authctxt, const char *password)
{
#ifndef HEIMDAL
krb5_creds creds;
krb5_principal server;
#endif
krb5_error_code problem;
krb5_ccache ccache = NULL;
int len;
char *client, *platform_client;
const char *errmsg;
/* get platform-specific kerberos client principal name (if it exists) */
platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
client = platform_client ? platform_client : authctxt->pw->pw_name;
temporarily_use_uid(authctxt->pw);
problem = krb5_init(authctxt);
if (problem)
goto out;
problem = krb5_parse_name(authctxt->krb5_ctx, client,
&authctxt->krb5_user);
if (problem)
goto out;
#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
problem = krb5_cc_new_unique(authctxt->krb5_ctx,
krb5_mcc_ops.prefix, NULL, &ccache);
# else
problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
# endif
if (problem)
goto out;
problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
authctxt->krb5_user);
if (problem)
goto out;
restore_uid();
problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
ccache, password, 1, NULL);
temporarily_use_uid(authctxt->pw);
if (problem)
goto out;
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
problem = krb5_cc_new_unique(authctxt->krb5_ctx,
krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
# else
problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
&authctxt->krb5_fwd_ccache);
# endif
if (problem)
goto out;
problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
authctxt->krb5_fwd_ccache);
krb5_cc_destroy(authctxt->krb5_ctx, ccache);
ccache = NULL;
if (problem)
goto out;
#else
problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
if (problem)
goto out;
problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
KRB5_NT_SRV_HST, &server);
if (problem)
goto out;
restore_uid();
problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
NULL, NULL, NULL);
krb5_free_principal(authctxt->krb5_ctx, server);
temporarily_use_uid(authctxt->pw);
if (problem)
goto out;
if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
authctxt->pw->pw_name)) {
problem = -1;
goto out;
}
problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
if (problem)
goto out;
problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
authctxt->krb5_user);
if (problem)
goto out;
problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
&creds);
if (problem)
goto out;
#endif
authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
len = strlen(authctxt->krb5_ticket_file) + 6;
authctxt->krb5_ccname = xmalloc(len);
snprintf(authctxt->krb5_ccname, len, "FILE:%s",
authctxt->krb5_ticket_file);
#ifdef USE_PAM
if (options.use_pam)
do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
#endif
out:
restore_uid();
free(platform_client);
if (problem) {
if (ccache)
krb5_cc_destroy(authctxt->krb5_ctx, ccache);
if (authctxt->krb5_ctx != NULL && problem!=-1) {
errmsg = krb5_get_error_message(authctxt->krb5_ctx,
problem);
debug("Kerberos password authentication failed: %s",
errmsg);
krb5_free_error_message(authctxt->krb5_ctx, errmsg);
} else
debug("Kerberos password authentication failed: %d",
problem);
krb5_cleanup_proc(authctxt);
if (options.kerberos_or_local_passwd)
return (-1);
else
return (0);
}
return (authctxt->valid ? 1 : 0);
}
void
krb5_cleanup_proc(Authctxt *authctxt)
{
debug("krb5_cleanup_proc called");
if (authctxt->krb5_fwd_ccache) {
krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
authctxt->krb5_fwd_ccache = NULL;
}
if (authctxt->krb5_user) {
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
authctxt->krb5_user = NULL;
}
if (authctxt->krb5_ctx) {
krb5_free_context(authctxt->krb5_ctx);
authctxt->krb5_ctx = NULL;
}
}
#ifndef HEIMDAL
krb5_error_code
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
int tmpfd, ret, oerrno;
char ccname[40];
mode_t old_umask;
ret = snprintf(ccname, sizeof(ccname),
"FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
if (ret < 0 || (size_t)ret >= sizeof(ccname))
return ENOMEM;
old_umask = umask(0177);
tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
umask(old_umask);
if (tmpfd == -1) {
logit("mkstemp(): %.100s", strerror(oerrno));
return oerrno;
}
if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
oerrno = errno;
logit("fchmod(): %.100s", strerror(oerrno));
close(tmpfd);
return oerrno;
}
close(tmpfd);
return (krb5_cc_resolve(ctx, ccname, ccache));
}
#endif /* !HEIMDAL */
#endif /* KRB5 */

View File

@@ -0,0 +1,620 @@
/* $OpenBSD: auth-options.c,v 1.68 2015/07/03 03:43:18 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* 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".
*/
#include "includes.h"
#include <sys/types.h>
#include <netdb.h>
#include <pwd.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "openbsd-compat/sys-queue.h"
#include "key.h" /* XXX for typedef */
#include "buffer.h" /* XXX for typedef */
#include "xmalloc.h"
#include "match.h"
#include "ssherr.h"
#include "log.h"
#include "canohost.h"
#include "sshbuf.h"
#include "misc.h"
#include "channels.h"
#include "servconf.h"
#include "sshkey.h"
#include "auth-options.h"
#include "hostfile.h"
#include "auth.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
int no_agent_forwarding_flag = 0;
int no_x11_forwarding_flag = 0;
int no_pty_flag = 0;
int no_user_rc = 0;
int key_is_cert_authority = 0;
/* "command=" option. */
char *forced_command = NULL;
/* "environment=" options. */
struct envstring *custom_environment = NULL;
/* "tunnel=" option. */
int forced_tun_device = -1;
/* "principals=" option. */
char *authorized_principals = NULL;
extern ServerOptions options;
void
auth_clear_options(void)
{
no_agent_forwarding_flag = 0;
no_port_forwarding_flag = 0;
no_pty_flag = 0;
no_x11_forwarding_flag = 0;
no_user_rc = 0;
key_is_cert_authority = 0;
while (custom_environment) {
struct envstring *ce = custom_environment;
custom_environment = ce->next;
free(ce->s);
free(ce);
}
if (forced_command) {
free(forced_command);
forced_command = NULL;
}
if (authorized_principals) {
free(authorized_principals);
authorized_principals = NULL;
}
forced_tun_device = -1;
channel_clear_permitted_opens();
}
/*
* return 1 if access is granted, 0 if not.
* side effect: sets key option flags
*/
int
auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
{
const char *cp;
int i;
/* reset options */
auth_clear_options();
if (!opts)
return 1;
while (*opts && *opts != ' ' && *opts != '\t') {
cp = "cert-authority";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
key_is_cert_authority = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-port-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
auth_debug_add("Port forwarding disabled.");
no_port_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
auth_debug_add("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
auth_debug_add("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
auth_debug_add("Pty allocation disabled.");
no_pty_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-user-rc";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
auth_debug_add("User rc file execution disabled.");
no_user_rc = 1;
opts += strlen(cp);
goto next_option;
}
cp = "command=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
if (forced_command != NULL)
free(forced_command);
forced_command = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
forced_command[i++] = '"';
continue;
}
forced_command[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(forced_command);
forced_command = NULL;
goto bad_option;
}
forced_command[i] = '\0';
auth_debug_add("Forced command.");
opts++;
goto next_option;
}
cp = "principals=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
if (authorized_principals != NULL)
free(authorized_principals);
authorized_principals = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
authorized_principals[i++] = '"';
continue;
}
authorized_principals[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(authorized_principals);
authorized_principals = NULL;
goto bad_option;
}
authorized_principals[i] = '\0';
auth_debug_add("principals: %.900s",
authorized_principals);
opts++;
goto next_option;
}
cp = "environment=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *s;
struct envstring *new_envstring;
opts += strlen(cp);
s = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
s[i++] = '"';
continue;
}
s[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(s);
goto bad_option;
}
s[i] = '\0';
opts++;
if (options.permit_user_env) {
auth_debug_add("Adding to environment: "
"%.900s", s);
debug("Adding to environment: %.900s", s);
new_envstring = xcalloc(1,
sizeof(*new_envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
s = NULL;
}
free(s);
goto next_option;
}
cp = "from=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
const char *remote_ip = get_remote_ipaddr();
const char *remote_host = get_canonical_hostname(
options.use_dns);
char *patterns = xmalloc(strlen(opts) + 1);
opts += strlen(cp);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(patterns);
goto bad_option;
}
patterns[i] = '\0';
opts++;
switch (match_host_and_ip(remote_host, remote_ip,
patterns)) {
case 1:
free(patterns);
/* Host name matches. */
goto next_option;
case -1:
debug("%.100s, line %lu: invalid criteria",
file, linenum);
auth_debug_add("%.100s, line %lu: "
"invalid criteria", file, linenum);
/* FALLTHROUGH */
case 0:
free(patterns);
logit("Authentication tried for %.100s with "
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s).",
pw->pw_name, remote_host, remote_ip);
auth_debug_add("Your host '%.200s' is not "
"permitted to use this key for login.",
remote_host);
break;
}
/* deny access */
return 0;
}
cp = "permitopen=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *host, *p;
int port;
char *patterns = xmalloc(strlen(opts) + 1);
opts += strlen(cp);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing "
"end quote", file, linenum);
free(patterns);
goto bad_option;
}
patterns[i] = '\0';
opts++;
p = patterns;
/* XXX - add streamlocal support */
host = hpdelim(&p);
if (host == NULL || strlen(host) >= NI_MAXHOST) {
debug("%.100s, line %lu: Bad permitopen "
"specification <%.100s>", file, linenum,
patterns);
auth_debug_add("%.100s, line %lu: "
"Bad permitopen specification", file,
linenum);
free(patterns);
goto bad_option;
}
host = cleanhostname(host);
if (p == NULL || (port = permitopen_port(p)) < 0) {
debug("%.100s, line %lu: Bad permitopen port "
"<%.100s>", file, linenum, p ? p : "");
auth_debug_add("%.100s, line %lu: "
"Bad permitopen port", file, linenum);
free(patterns);
goto bad_option;
}
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
channel_add_permitted_opens(host, port);
free(patterns);
goto next_option;
}
cp = "tunnel=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *tun = NULL;
opts += strlen(cp);
tun = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
tun[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(tun);
forced_tun_device = -1;
goto bad_option;
}
tun[i] = '\0';
forced_tun_device = a2tun(tun, NULL);
free(tun);
if (forced_tun_device == SSH_TUNID_ERR) {
debug("%.100s, line %lu: invalid tun device",
file, linenum);
auth_debug_add("%.100s, line %lu: invalid tun device",
file, linenum);
forced_tun_device = -1;
goto bad_option;
}
auth_debug_add("Forced tun device: %d", forced_tun_device);
opts++;
goto next_option;
}
next_option:
/*
* Skip the comma, and move to the next option
* (or break out if there are no more).
*/
if (!*opts)
fatal("Bugs in auth-options.c option processing.");
if (*opts == ' ' || *opts == '\t')
break; /* End of options. */
if (*opts != ',')
goto bad_option;
opts++;
/* Process the next option. */
}
/* grant access */
return 1;
bad_option:
logit("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
/* deny access */
return 0;
}
#define OPTIONS_CRITICAL 1
#define OPTIONS_EXTENSIONS 2
static int
parse_option_list(struct sshbuf *oblob, struct passwd *pw,
u_int which, int crit,
int *cert_no_port_forwarding_flag,
int *cert_no_agent_forwarding_flag,
int *cert_no_x11_forwarding_flag,
int *cert_no_pty_flag,
int *cert_no_user_rc,
char **cert_forced_command,
int *cert_source_address_done)
{
char *command, *allowed;
const char *remote_ip;
char *name = NULL;
struct sshbuf *c = NULL, *data = NULL;
int r, ret = -1, result, found;
if ((c = sshbuf_fromb(oblob)) == NULL) {
error("%s: sshbuf_fromb failed", __func__);
goto out;
}
while (sshbuf_len(c) > 0) {
sshbuf_free(data);
data = NULL;
if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 ||
(r = sshbuf_froms(c, &data)) != 0) {
error("Unable to parse certificate options: %s",
ssh_err(r));
goto out;
}
debug3("found certificate option \"%.100s\" len %zu",
name, sshbuf_len(data));
found = 0;
if ((which & OPTIONS_EXTENSIONS) != 0) {
if (strcmp(name, "permit-X11-forwarding") == 0) {
*cert_no_x11_forwarding_flag = 0;
found = 1;
} else if (strcmp(name,
"permit-agent-forwarding") == 0) {
*cert_no_agent_forwarding_flag = 0;
found = 1;
} else if (strcmp(name,
"permit-port-forwarding") == 0) {
*cert_no_port_forwarding_flag = 0;
found = 1;
} else if (strcmp(name, "permit-pty") == 0) {
*cert_no_pty_flag = 0;
found = 1;
} else if (strcmp(name, "permit-user-rc") == 0) {
*cert_no_user_rc = 0;
found = 1;
}
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
if (strcmp(name, "force-command") == 0) {
if ((r = sshbuf_get_cstring(data, &command,
NULL)) != 0) {
error("Unable to parse \"%s\" "
"section: %s", name, ssh_err(r));
goto out;
}
if (*cert_forced_command != NULL) {
error("Certificate has multiple "
"force-command options");
free(command);
goto out;
}
*cert_forced_command = command;
found = 1;
}
if (strcmp(name, "source-address") == 0) {
if ((r = sshbuf_get_cstring(data, &allowed,
NULL)) != 0) {
error("Unable to parse \"%s\" "
"section: %s", name, ssh_err(r));
goto out;
}
if ((*cert_source_address_done)++) {
error("Certificate has multiple "
"source-address options");
free(allowed);
goto out;
}
remote_ip = get_remote_ipaddr();
result = addr_match_cidr_list(remote_ip,
allowed);
free(allowed);
switch (result) {
case 1:
/* accepted */
break;
case 0:
/* no match */
logit("Authentication tried for %.100s "
"with valid certificate but not "
"from a permitted host "
"(ip=%.200s).", pw->pw_name,
remote_ip);
auth_debug_add("Your address '%.200s' "
"is not permitted to use this "
"certificate for login.",
remote_ip);
goto out;
case -1:
default:
error("Certificate source-address "
"contents invalid");
goto out;
}
found = 1;
}
}
if (!found) {
if (crit) {
error("Certificate critical option \"%s\" "
"is not supported", name);
goto out;
} else {
logit("Certificate extension \"%s\" "
"is not supported", name);
}
} else if (sshbuf_len(data) != 0) {
error("Certificate option \"%s\" corrupt "
"(extra data)", name);
goto out;
}
free(name);
name = NULL;
}
/* successfully parsed all options */
ret = 0;
out:
if (ret != 0 &&
cert_forced_command != NULL &&
*cert_forced_command != NULL) {
free(*cert_forced_command);
*cert_forced_command = NULL;
}
if (name != NULL)
free(name);
sshbuf_free(data);
sshbuf_free(c);
return ret;
}
/*
* Set options from critical certificate options. These supersede user key
* options so this must be called after auth_parse_options().
*/
int
auth_cert_options(struct sshkey *k, struct passwd *pw)
{
int cert_no_port_forwarding_flag = 1;
int cert_no_agent_forwarding_flag = 1;
int cert_no_x11_forwarding_flag = 1;
int cert_no_pty_flag = 1;
int cert_no_user_rc = 1;
char *cert_forced_command = NULL;
int cert_source_address_done = 0;
/* Separate options and extensions for v01 certs */
if (parse_option_list(k->cert->critical, pw,
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
if (parse_option_list(k->cert->extensions, pw,
OPTIONS_EXTENSIONS, 0,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
NULL, NULL) == -1)
return -1;
no_port_forwarding_flag |= cert_no_port_forwarding_flag;
no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
no_pty_flag |= cert_no_pty_flag;
no_user_rc |= cert_no_user_rc;
/* CA-specified forced command supersedes key option */
if (cert_forced_command != NULL) {
if (forced_command != NULL)
free(forced_command);
forced_command = cert_forced_command;
}
return 0;
}

View File

@@ -0,0 +1,40 @@
/* $OpenBSD: auth-options.h,v 1.21 2015/01/14 10:30:34 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* 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".
*/
#ifndef AUTH_OPTIONS_H
#define AUTH_OPTIONS_H
/* Linked list of custom environment strings */
struct envstring {
struct envstring *next;
char *s;
};
/* Flags that may be set in authorized_keys options. */
extern int no_port_forwarding_flag;
extern int no_agent_forwarding_flag;
extern int no_x11_forwarding_flag;
extern int no_pty_flag;
extern int no_user_rc;
extern char *forced_command;
extern struct envstring *custom_environment;
extern int forced_tun_device;
extern int key_is_cert_authority;
extern char *authorized_principals;
int auth_parse_options(struct passwd *, char *, char *, u_long);
void auth_clear_options(void);
int auth_cert_options(struct sshkey *, struct passwd *);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/* $Id: auth-pam.h,v 1.27 2004/09/11 12:17:26 dtucker Exp $ */
/*
* Copyright (c) 2000 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef USE_PAM
#if !defined(SSHD_PAM_SERVICE)
# define SSHD_PAM_SERVICE __progname
#endif
void start_pam(Authctxt *);
void finish_pam(void);
u_int do_pam_account(void);
void do_pam_session(void);
void do_pam_set_tty(const char *);
void do_pam_setcred(int );
void do_pam_chauthtok(void);
int do_pam_putenv(char *, char *);
char ** fetch_pam_environment(void);
char ** fetch_pam_child_environment(void);
void free_pam_environment(char **);
void sshpam_thread_cleanup(void);
void sshpam_cleanup(void);
int sshpam_auth_passwd(Authctxt *, const char *);
int is_pam_session_open(void);
#endif /* USE_PAM */

View File

@@ -0,0 +1,216 @@
/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Password authentication. This file contains the functions to check whether
* the password is valid for the user.
*
* 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".
*
* Copyright (c) 1999 Dug Song. All rights reserved.
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
extern Buffer loginmsg;
extern ServerOptions options;
#ifdef HAVE_LOGIN_CAP
extern login_cap_t *lc;
#endif
#define DAY (24L * 60 * 60) /* 1 day in seconds */
#define TWO_WEEKS (2L * 7 * DAY) /* 2 weeks in seconds */
void
disable_forwarding(void)
{
no_port_forwarding_flag = 1;
no_agent_forwarding_flag = 1;
no_x11_forwarding_flag = 1;
}
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
auth_password(Authctxt *authctxt, const char *password)
{
struct passwd * pw = authctxt->pw;
int result, ok = authctxt->valid;
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
static int expire_checked = 0;
#endif
#ifndef HAVE_CYGWIN
if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
ok = 0;
#endif
if (*password == '\0' && options.permit_empty_passwd == 0)
return 0;
#ifdef KRB5
if (options.kerberos_authentication == 1) {
int ret = auth_krb5_password(authctxt, password);
if (ret == 1 || ret == 0)
return ret && ok;
/* Fall back to ordinary passwd authentication. */
}
#endif
#ifdef HAVE_CYGWIN
{
HANDLE hToken = cygwin_logon_user(pw, password);
if (hToken == INVALID_HANDLE_VALUE)
return 0;
cygwin_set_impersonation_token(hToken);
return ok;
}
#endif
#ifdef USE_PAM
if (options.use_pam)
return (sshpam_auth_passwd(authctxt, password) && ok);
#endif
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
if (!expire_checked) {
expire_checked = 1;
if (auth_shadow_pwexpired(authctxt))
authctxt->force_pwchange = 1;
}
#endif
result = sys_auth_passwd(authctxt, password);
if (authctxt->force_pwchange)
disable_forwarding();
return (result && ok);
}
#ifdef BSD_AUTH
static void
warn_expiry(Authctxt *authctxt, auth_session_t *as)
{
char buf[256];
quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime;
pwwarntime = acwarntime = TWO_WEEKS;
pwtimeleft = auth_check_change(as);
actimeleft = auth_check_expire(as);
#ifdef HAVE_LOGIN_CAP
if (authctxt->valid) {
pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS,
TWO_WEEKS);
acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS,
TWO_WEEKS);
}
#endif
if (pwtimeleft != 0 && pwtimeleft < pwwarntime) {
daysleft = pwtimeleft / DAY + 1;
snprintf(buf, sizeof(buf),
"Your password will expire in %lld day%s.\n",
daysleft, daysleft == 1 ? "" : "s");
buffer_append(&loginmsg, buf, strlen(buf));
}
if (actimeleft != 0 && actimeleft < acwarntime) {
daysleft = actimeleft / DAY + 1;
snprintf(buf, sizeof(buf),
"Your account will expire in %lld day%s.\n",
daysleft, daysleft == 1 ? "" : "s");
buffer_append(&loginmsg, buf, strlen(buf));
}
}
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
{
struct passwd *pw = authctxt->pw;
auth_session_t *as;
static int expire_checked = 0;
as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
(char *)password);
if (as == NULL)
return (0);
if (auth_getstate(as) & AUTH_PWEXPIRED) {
auth_close(as);
disable_forwarding();
authctxt->force_pwchange = 1;
return (1);
} else {
if (!expire_checked) {
expire_checked = 1;
warn_expiry(authctxt, as);
}
return (auth_close(as));
}
}
#elif !defined(CUSTOM_SYS_AUTH_PASSWD)
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
{
struct passwd *pw = authctxt->pw;
char *encrypted_password;
/* Just use the supplied fake password if authctxt is invalid */
char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
/* Check for users with no password. */
if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
return (1);
/* Encrypt the candidate password using the proper salt. */
encrypted_password = xcrypt(password,
(pw_password[0] && pw_password[1]) ? pw_password : "xx");
/*
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return encrypted_password != NULL &&
strcmp(encrypted_password, pw_password) == 0;
}
#endif

View File

@@ -0,0 +1,108 @@
/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
* authentication.
*
* 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".
*/
#include "includes.h"
#ifdef WITH_SSH1
#include <sys/types.h>
#include <pwd.h>
#include <stdarg.h>
#include "packet.h"
#include "uidswap.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
#include "pathnames.h"
#include "auth.h"
#include "canohost.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
int
auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
Key *client_host_key)
{
HostStatus host_status;
if (auth_key_is_revoked(client_host_key))
return 0;
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, cuser))
return 0;
host_status = check_key_in_hostfiles(pw, client_host_key,
chost, _PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
return (host_status == HOST_OK);
}
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
*/
int
auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
{
char *chost;
struct passwd *pw = authctxt->pw;
debug("Trying rhosts with RSA host authentication for client user %.100s",
cuser);
if (!authctxt->valid || client_host_key == NULL ||
client_host_key->rsa == NULL)
return 0;
chost = (char *)get_canonical_hostname(options.use_dns);
debug("Rhosts RSA authentication: canonical host %.900s", chost);
if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
}
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
if (!auth_rsa_challenge_dialog(client_host_key)) {
logit("Client on %.800s failed to respond correctly to host authentication.",
chost);
return 0;
}
/*
* We have authenticated the user using .rhosts or /etc/hosts.equiv,
* and the host using RSA. We accept the authentication.
*/
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, cuser, chost);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}
#endif /* WITH_SSH1 */

View File

@@ -0,0 +1,341 @@
/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Rhosts authentication. This file contains code to check whether to admit
* the login based on rhosts authentication. This file also processes
* /etc/hosts.equiv.
*
* 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".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_NETGROUP_H
# include <netgroup.h>
#endif
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include "packet.h"
#include "buffer.h"
#include "uidswap.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "canohost.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
/* import */
extern ServerOptions options;
extern int use_privsep;
/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
* /etc/hosts.equiv). This returns true if authentication can be granted
* based on the file, and returns zero otherwise.
*/
static int
check_rhosts_file(const char *filename, const char *hostname,
const char *ipaddr, const char *client_user,
const char *server_user)
{
FILE *f;
#define RBUFLN 1024
char buf[RBUFLN];/* Must not be larger than host, user, dummy below. */
int fd;
struct stat st;
/* Open the .rhosts file, deny if unreadable */
if ((fd = open(filename, O_RDONLY|O_NONBLOCK)) == -1)
return 0;
if (fstat(fd, &st) == -1) {
close(fd);
return 0;
}
if (!S_ISREG(st.st_mode)) {
logit("User %s hosts file %s is not a regular file",
server_user, filename);
close(fd);
return 0;
}
unset_nonblock(fd);
if ((f = fdopen(fd, "r")) == NULL) {
close(fd);
return 0;
}
while (fgets(buf, sizeof(buf), f)) {
/* All three must have length >= buf to avoid overflows. */
char hostbuf[RBUFLN], userbuf[RBUFLN], dummy[RBUFLN];
char *host, *user, *cp;
int negated;
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
;
if (*cp == '#' || *cp == '\n' || !*cp)
continue;
/*
* NO_PLUS is supported at least on OSF/1. We skip it (we
* don't ever support the plus syntax).
*/
if (strncmp(cp, "NO_PLUS", 7) == 0)
continue;
/*
* This should be safe because each buffer is as big as the
* whole string, and thus cannot be overwritten.
*/
switch (sscanf(buf, "%1023s %1023s %1023s", hostbuf, userbuf,
dummy)) {
case 0:
auth_debug_add("Found empty line in %.100s.", filename);
continue;
case 1:
/* Host name only. */
strlcpy(userbuf, server_user, sizeof(userbuf));
break;
case 2:
/* Got both host and user name. */
break;
case 3:
auth_debug_add("Found garbage in %.100s.", filename);
continue;
default:
/* Weird... */
continue;
}
host = hostbuf;
user = userbuf;
negated = 0;
/* Process negated host names, or positive netgroups. */
if (host[0] == '-') {
negated = 1;
host++;
} else if (host[0] == '+')
host++;
if (user[0] == '-') {
negated = 1;
user++;
} else if (user[0] == '+')
user++;
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0]) {
/* We come here if either was '+' or '-'. */
auth_debug_add("Ignoring wild host/user names "
"in %.100s.", filename);
continue;
}
/* Verify that host name matches. */
if (host[0] == '@') {
if (!innetgr(host + 1, hostname, NULL, NULL) &&
!innetgr(host + 1, ipaddr, NULL, NULL))
continue;
} else if (strcasecmp(host, hostname) &&
strcmp(host, ipaddr) != 0)
continue; /* Different hostname. */
/* Verify that user name matches. */
if (user[0] == '@') {
if (!innetgr(user + 1, NULL, client_user, NULL))
continue;
} else if (strcmp(user, client_user) != 0)
continue; /* Different username. */
/* Found the user and host. */
fclose(f);
/* If the entry was negated, deny access. */
if (negated) {
auth_debug_add("Matched negative entry in %.100s.",
filename);
return 0;
}
/* Accept authentication. */
return 1;
}
/* Authentication using this file denied. */
fclose(f);
return 0;
}
/*
* Tries to authenticate the user using the .shosts or .rhosts file. Returns
* true if authentication succeeds. If ignore_rhosts is true, only
* /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored).
*/
int
auth_rhosts(struct passwd *pw, const char *client_user)
{
const char *hostname, *ipaddr;
hostname = get_canonical_hostname(options.use_dns);
ipaddr = get_remote_ipaddr();
return auth_rhosts2(pw, client_user, hostname, ipaddr);
}
static int
auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
const char *ipaddr)
{
char buf[1024];
struct stat st;
static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
u_int rhosts_file_index;
debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s",
client_user, hostname, ipaddr);
/* Switch to the user's uid. */
temporarily_use_uid(pw);
/*
* Quick check: if the user has no .shosts or .rhosts files and
* no system hosts.equiv/shosts.equiv files exist then return
* failure immediately without doing costly lookups from name
* servers.
*/
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) >= 0)
break;
}
/* Switch back to privileged uid. */
restore_uid();
/*
* Deny if The user has no .shosts or .rhosts file and there
* are no system-wide files.
*/
if (!rhosts_files[rhosts_file_index] &&
stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) {
debug3("%s: no hosts access files exist", __func__);
return 0;
}
/*
* If not logging in as superuser, try /etc/hosts.equiv and
* shosts.equiv.
*/
if (pw->pw_uid == 0)
debug3("%s: root user, ignoring system hosts files", __func__);
else {
if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
auth_debug_add("Accepted for %.100s [%.100s] by "
"/etc/hosts.equiv.", hostname, ipaddr);
return 1;
}
if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
auth_debug_add("Accepted for %.100s [%.100s] by "
"%.100s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
return 1;
}
}
/*
* Check that the home directory is owned by root or the user, and is
* not group or world writable.
*/
if (stat(pw->pw_dir, &st) < 0) {
logit("Rhosts authentication refused for %.100s: "
"no home directory %.200s", pw->pw_name, pw->pw_dir);
auth_debug_add("Rhosts authentication refused for %.100s: "
"no home directory %.200s", pw->pw_name, pw->pw_dir);
return 0;
}
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
logit("Rhosts authentication refused for %.100s: "
"bad ownership or modes for home directory.", pw->pw_name);
auth_debug_add("Rhosts authentication refused for %.100s: "
"bad ownership or modes for home directory.", pw->pw_name);
return 0;
}
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
/* Check all .rhosts files (currently .shosts and .rhosts). */
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) < 0)
continue;
/*
* Make sure that the file is either owned by the user or by
* root, and make sure it is not writable by anyone but the
* owner. This is to help avoid novices accidentally
* allowing access to their account by anyone.
*/
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
pw->pw_name, buf);
auth_debug_add("Bad file modes for %.200s", buf);
continue;
}
/*
* Check if we have been configured to ignore .rhosts
* and .shosts files.
*/
if (options.ignore_rhosts) {
auth_debug_add("Server has been configured to "
"ignore %.100s.", rhosts_files[rhosts_file_index]);
continue;
}
/* Check if authentication is permitted by the file. */
if (check_rhosts_file(buf, hostname, ipaddr,
client_user, pw->pw_name)) {
auth_debug_add("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
auth_debug_add("Accepted host %s ip %s client_user "
"%s server_user %s", hostname, ipaddr,
client_user, pw->pw_name);
return 1;
}
}
/* Restore the privileged uid. */
restore_uid();
return 0;
}
int
auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
const char *ipaddr)
{
return auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
}

View File

@@ -0,0 +1,349 @@
/* $OpenBSD: auth-rsa.c,v 1.90 2015/01/28 22:36:00 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* RSA-based authentication. This code determines whether to admit a login
* based on RSA authentication. This file also contains functions to check
* validity of the host key.
*
* 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".
*/
#include "includes.h"
#ifdef WITH_SSH1
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/rsa.h>
#include <pwd.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "xmalloc.h"
#include "rsa.h"
#include "packet.h"
#include "ssh1.h"
#include "uidswap.h"
#include "match.h"
#include "buffer.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "auth-options.h"
#include "hostfile.h"
#include "auth.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "ssh.h"
#include "digest.h"
/* import */
extern ServerOptions options;
/*
* Session identifier that is used to bind key exchange and authentication
* responses to a particular session.
*/
extern u_char session_id[16];
/*
* The .ssh/authorized_keys file contains public keys, one per line, in the
* following format:
* options bits e n comment
* where bits, e and n are decimal numbers,
* and comment is any string of characters up to newline. The maximum
* length of a line is SSH_MAX_PUBKEY_BYTES characters. See sshd(8) for a
* description of the options.
*/
BIGNUM *
auth_rsa_generate_challenge(Key *key)
{
BIGNUM *challenge;
BN_CTX *ctx;
if ((challenge = BN_new()) == NULL)
fatal("auth_rsa_generate_challenge: BN_new() failed");
/* Generate a random challenge. */
if (BN_rand(challenge, 256, 0, 0) == 0)
fatal("auth_rsa_generate_challenge: BN_rand failed");
if ((ctx = BN_CTX_new()) == NULL)
fatal("auth_rsa_generate_challenge: BN_CTX_new failed");
if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0)
fatal("auth_rsa_generate_challenge: BN_mod failed");
BN_CTX_free(ctx);
return challenge;
}
int
auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
{
u_char buf[32], mdbuf[16];
struct ssh_digest_ctx *md;
int len;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("%s: RSA modulus too small: %d < minimum %d bits",
__func__,
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return (0);
}
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("%s: bad challenge length %d", __func__, len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
ssh_digest_update(md, buf, 32) < 0 ||
ssh_digest_update(md, session_id, 16) < 0 ||
ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
fatal("%s: md5 failed", __func__);
ssh_digest_free(md);
/* Verify that the response is the original challenge. */
if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return (0);
}
/* Correct answer. */
return (1);
}
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
* our challenge; returns zero if the client gives a wrong answer.
*/
int
auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
u_char response[16];
int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_new() failed");
challenge = PRIVSEP(auth_rsa_generate_challenge(key));
/* Encrypt the challenge with the public key. */
if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0)
fatal("%s: rsa_public_encrypt failed", __func__);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
packet_put_bignum(encrypted_challenge);
packet_send();
BN_clear_free(encrypted_challenge);
packet_write_wait();
/* Wait for a response. */
packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
for (i = 0; i < 16; i++)
response[i] = (u_char)packet_get_char();
packet_check_eom();
success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
BN_clear_free(challenge);
return (success);
}
static int
rsa_key_allowed_in_file(struct passwd *pw, char *file,
const BIGNUM *client_n, Key **rkey)
{
char *fp, line[SSH_MAX_PUBKEY_BYTES];
int allowed = 0, bits;
FILE *f;
u_long linenum = 0;
Key *key;
debug("trying public RSA key file %s", file);
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
return 0;
/*
* Go though the accepted keys, looking for the current key. If
* found, perform a challenge-response dialog to verify that the
* user really has the corresponding private key.
*/
key = key_new(KEY_RSA1);
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
char *cp;
char *key_options;
int keybits;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
/*
* Check if there are options for this key, and if so,
* save their starting address and skip the option part
* for now. If there are no options, set the starting
* address to NULL.
*/
if (*cp < '0' || *cp > '9') {
int quoted = 0;
key_options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
} else
key_options = NULL;
/* Parse the key from the line. */
if (hostfile_read_key(&cp, &bits, key) == 0) {
debug("%.100s, line %lu: non ssh1 key syntax",
file, linenum);
continue;
}
/* cp now points to the comment part. */
/*
* Check if the we have found the desired key (identified
* by its modulus).
*/
if (BN_cmp(key->rsa->n, client_n) != 0)
continue;
/* check the real bits */
keybits = BN_num_bits(key->rsa->n);
if (keybits < 0 || bits != keybits)
logit("Warning: %s, line %lu: keysize mismatch: "
"actual %d vs. announced %d.",
file, linenum, BN_num_bits(key->rsa->n), bits);
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(key), fp);
free(fp);
/* Never accept a revoked key */
if (auth_key_is_revoked(key))
break;
/* We have found the desired key. */
/*
* If our options do not allow this key to be used,
* do not send challenge.
*/
if (!auth_parse_options(pw, key_options, file, linenum))
continue;
if (key_is_cert_authority)
continue;
/* break out, this key is allowed */
allowed = 1;
break;
}
/* Close the file. */
fclose(f);
/* return key if allowed */
if (allowed && rkey != NULL)
*rkey = key;
else
key_free(key);
return allowed;
}
/*
* check if there's user key matching client_n,
* return key if login is allowed, NULL otherwise
*/
int
auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
char *file;
u_int i, allowed = 0;
temporarily_use_uid(pw);
for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
free(file);
}
restore_uid();
return allowed;
}
/*
* Performs the RSA authentication dialog with the client. This returns
* 0 if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int
auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
{
Key *key;
struct passwd *pw = authctxt->pw;
/* no user given */
if (!authctxt->valid)
return 0;
if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
auth_clear_options();
return (0);
}
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(key)) {
/* Wrong response. */
verbose("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
/*
* Break out of the loop. Otherwise we might send
* another challenge and break the protocol.
*/
key_free(key);
return (0);
}
/*
* Correct response. The client has been successfully
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
pubkey_auth_info(authctxt, key, NULL);
packet_send_debug("RSA authentication accepted.");
return (1);
}
#endif /* WITH_SSH1 */

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2004 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
#include <shadow.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "buffer.h"
#include "log.h"
#ifdef DAY
# undef DAY
#endif
#define DAY (24L * 60 * 60) /* 1 day in seconds */
extern Buffer loginmsg;
/*
* For the account and password expiration functions, we assume the expiry
* occurs the day after the day specified.
*/
/*
* Check if specified account is expired. Returns 1 if account is expired,
* 0 otherwise.
*/
int
auth_shadow_acctexpired(struct spwd *spw)
{
time_t today;
int daysleft;
char buf[256];
today = time(NULL) / DAY;
daysleft = spw->sp_expire - today;
debug3("%s: today %d sp_expire %d days left %d", __func__, (int)today,
(int)spw->sp_expire, daysleft);
if (spw->sp_expire == -1) {
debug3("account expiration disabled");
} else if (daysleft < 0) {
logit("Account %.100s has expired", spw->sp_namp);
return 1;
} else if (daysleft <= spw->sp_warn) {
debug3("account will expire in %d days", daysleft);
snprintf(buf, sizeof(buf),
"Your account will expire in %d day%s.\n", daysleft,
daysleft == 1 ? "" : "s");
buffer_append(&loginmsg, buf, strlen(buf));
}
return 0;
}
/*
* Checks password expiry for platforms that use shadow passwd files.
* Returns: 1 = password expired, 0 = password not expired
*/
int
auth_shadow_pwexpired(Authctxt *ctxt)
{
struct spwd *spw = NULL;
const char *user = ctxt->pw->pw_name;
char buf[256];
time_t today;
int daysleft, disabled = 0;
if ((spw = getspnam((char *)user)) == NULL) {
error("Could not get shadow information for %.100s", user);
return 0;
}
today = time(NULL) / DAY;
debug3("%s: today %d sp_lstchg %d sp_max %d", __func__, (int)today,
(int)spw->sp_lstchg, (int)spw->sp_max);
#if defined(__hpux) && !defined(HAVE_SECUREWARE)
if (iscomsec()) {
struct pr_passwd *pr;
pr = getprpwnam((char *)user);
/* Test for Trusted Mode expiry disabled */
if (pr != NULL && pr->ufld.fd_min == 0 &&
pr->ufld.fd_lifetime == 0 && pr->ufld.fd_expire == 0 &&
pr->ufld.fd_pw_expire_warning == 0 &&
pr->ufld.fd_schange != 0)
disabled = 1;
}
#endif
/* TODO: check sp_inact */
daysleft = spw->sp_lstchg + spw->sp_max - today;
if (disabled) {
debug3("password expiration disabled");
} else if (spw->sp_lstchg == 0) {
logit("User %.100s password has expired (root forced)", user);
return 1;
} else if (spw->sp_max == -1) {
debug3("password expiration disabled");
} else if (daysleft < 0) {
logit("User %.100s password has expired (password aged)", user);
return 1;
} else if (daysleft <= spw->sp_warn) {
debug3("password will expire in %d days", daysleft);
snprintf(buf, sizeof(buf),
"Your password will expire in %d day%s.\n", daysleft,
daysleft == 1 ? "" : "s");
buffer_append(&loginmsg, buf, strlen(buf));
}
return 0;
}
#endif /* USE_SHADOW && HAS_SHADOW_EXPIRE */

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2002 Chris Adams. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef HAVE_OSF_SIA
#include <sia.h>
#include <siad.h>
#include <pwd.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include "ssh.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-sia.h"
#include "log.h"
#include "servconf.h"
#include "canohost.h"
#include "uidswap.h"
extern ServerOptions options;
extern int saved_argc;
extern char **saved_argv;
int
sys_auth_passwd(Authctxt *authctxt, const char *pass)
{
int ret;
SIAENTITY *ent = NULL;
const char *host;
host = get_canonical_hostname(options.use_dns);
if (!authctxt->user || pass == NULL || pass[0] == '\0')
return (0);
if (sia_ses_init(&ent, saved_argc, saved_argv, host, authctxt->user,
NULL, 0, NULL) != SIASUCCESS)
return (0);
if ((ret = sia_ses_authent(NULL, pass, ent)) != SIASUCCESS) {
error("Couldn't authenticate %s from %s",
authctxt->user, host);
if (ret & SIASTOP)
sia_ses_release(&ent);
return (0);
}
sia_ses_release(&ent);
return (1);
}
void
session_setup_sia(struct passwd *pw, char *tty)
{
SIAENTITY *ent = NULL;
const char *host;
host = get_canonical_hostname(options.use_dns);
if (sia_ses_init(&ent, saved_argc, saved_argv, host, pw->pw_name,
tty, 0, NULL) != SIASUCCESS)
fatal("sia_ses_init failed");
if (sia_make_entity_pwd(pw, ent) != SIASUCCESS) {
sia_ses_release(&ent);
fatal("sia_make_entity_pwd failed");
}
ent->authtype = SIA_A_NONE;
if (sia_ses_estab(sia_collect_trm, ent) != SIASUCCESS)
fatal("Couldn't establish session for %s from %s",
pw->pw_name, host);
if (sia_ses_launch(sia_collect_trm, ent) != SIASUCCESS)
fatal("Couldn't launch session for %s from %s",
pw->pw_name, host);
sia_ses_release(&ent);
setuid(0);
permanently_set_uid(pw);
}
#endif /* HAVE_OSF_SIA */

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2002 Chris Adams. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef HAVE_OSF_SIA
void session_setup_sia(struct passwd *, char *);
#endif /* HAVE_OSF_SIA */

View File

@@ -0,0 +1,108 @@
/* $OpenBSD: auth-skey.c,v 1.27 2007/01/21 01:41:54 stevesk Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef SKEY
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <skey.h>
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "ssh-gss.h"
#include "log.h"
#include "monitor_wrap.h"
static void *
skey_init_ctx(Authctxt *authctxt)
{
return authctxt;
}
int
skey_query(void *ctx, char **name, char **infotxt,
u_int* numprompts, char ***prompts, u_int **echo_on)
{
Authctxt *authctxt = ctx;
char challenge[1024];
struct skey skey;
if (_compat_skeychallenge(&skey, authctxt->user, challenge,
sizeof(challenge)) == -1)
return -1;
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xcalloc(*numprompts, sizeof(char *));
*echo_on = xcalloc(*numprompts, sizeof(u_int));
xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
return 0;
}
int
skey_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
if (authctxt->valid &&
numresponses == 1 &&
skey_haskey(authctxt->pw->pw_name) == 0 &&
skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1)
return 0;
return -1;
}
static void
skey_free_ctx(void *ctx)
{
/* we don't have a special context */
}
KbdintDevice skey_device = {
"skey",
skey_init_ctx,
skey_query,
skey_respond,
skey_free_ctx
};
KbdintDevice mm_skey_device = {
"skey",
skey_init_ctx,
mm_skey_query,
mm_skey_respond,
skey_free_ctx
};
#endif /* SKEY */

775
crypto/external/bsd/openssh/dist/auth.c vendored Normal file
View File

@@ -0,0 +1,775 @@
/* $OpenBSD: auth.c,v 1.113 2015/08/21 03:42:19 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <pwd.h>
#ifdef HAVE_LOGIN_H
#include <login.h>
#endif
#ifdef USE_SHADOW
#include <shadow.h>
#endif
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "xmalloc.h"
#include "match.h"
#include "groupaccess.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "canohost.h"
#include "uidswap.h"
#include "packet.h"
#include "loginrec.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "authfile.h"
#include "monitor_wrap.h"
#include "authfile.h"
#include "ssherr.h"
#include "compat.h"
/* import */
extern ServerOptions options;
extern int use_privsep;
extern Buffer loginmsg;
extern struct passwd *privsep_pw;
/* Debugging messages */
Buffer auth_debug;
int auth_debug_init;
/*
* Check if the user is allowed to log in via ssh. If user is listed
* in DenyUsers or one of user's groups is listed in DenyGroups, false
* will be returned. If AllowUsers isn't empty and user isn't listed
* there, or if AllowGroups isn't empty and one of user's groups isn't
* listed there, false will be returned.
* If the user's shell is not executable, false will be returned.
* Otherwise true is returned.
*/
int
allowed_user(struct passwd * pw)
{
struct stat st;
const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
u_int i;
#ifdef USE_SHADOW
struct spwd *spw = NULL;
#endif
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
if (!pw || !pw->pw_name)
return 0;
#ifdef USE_SHADOW
if (!options.use_pam)
spw = getspnam(pw->pw_name);
#ifdef HAS_SHADOW_EXPIRE
if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
return 0;
#endif /* HAS_SHADOW_EXPIRE */
#endif /* USE_SHADOW */
/* grab passwd field for locked account check */
passwd = pw->pw_passwd;
#ifdef USE_SHADOW
if (spw != NULL)
#ifdef USE_LIBIAF
passwd = get_iaf_password(pw);
#else
passwd = spw->sp_pwdp;
#endif /* USE_LIBIAF */
#endif
/* check for locked account */
if (!options.use_pam && passwd && *passwd) {
int locked = 0;
#ifdef LOCKED_PASSWD_STRING
if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
locked = 1;
#endif
#ifdef LOCKED_PASSWD_PREFIX
if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
strlen(LOCKED_PASSWD_PREFIX)) == 0)
locked = 1;
#endif
#ifdef LOCKED_PASSWD_SUBSTR
if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
locked = 1;
#endif
#ifdef USE_LIBIAF
free((void *) passwd);
#endif /* USE_LIBIAF */
if (locked) {
logit("User %.100s not allowed because account is locked",
pw->pw_name);
return 0;
}
}
/*
* Deny if shell does not exist or is not executable unless we
* are chrooting.
*/
if (options.chroot_directory == NULL ||
strcasecmp(options.chroot_directory, "none") == 0) {
char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
_PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
if (stat(shell, &st) != 0) {
logit("User %.100s not allowed because shell %.100s "
"does not exist", pw->pw_name, shell);
free(shell);
return 0;
}
if (S_ISREG(st.st_mode) == 0 ||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
logit("User %.100s not allowed because shell %.100s "
"is not executable", pw->pw_name, shell);
free(shell);
return 0;
}
free(shell);
}
if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
options.num_deny_groups > 0 || options.num_allow_groups > 0) {
hostname = get_canonical_hostname(options.use_dns);
ipaddr = get_remote_ipaddr();
}
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i])) {
logit("User %.100s from %.100s not allowed "
"because listed in DenyUsers",
pw->pw_name, hostname);
return 0;
}
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users) {
logit("User %.100s from %.100s not allowed because "
"not listed in AllowUsers", pw->pw_name, hostname);
return 0;
}
}
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
/* Get the user's group access list (primary and supplementary) */
if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
logit("User %.100s from %.100s not allowed because "
"not in any group", pw->pw_name, hostname);
return 0;
}
/* Return false if one of user's groups is listed in DenyGroups */
if (options.num_deny_groups > 0)
if (ga_match(options.deny_groups,
options.num_deny_groups)) {
ga_free();
logit("User %.100s from %.100s not allowed "
"because a group is listed in DenyGroups",
pw->pw_name, hostname);
return 0;
}
/*
* Return false if AllowGroups isn't empty and one of user's groups
* isn't listed there
*/
if (options.num_allow_groups > 0)
if (!ga_match(options.allow_groups,
options.num_allow_groups)) {
ga_free();
logit("User %.100s from %.100s not allowed "
"because none of user's groups are listed "
"in AllowGroups", pw->pw_name, hostname);
return 0;
}
ga_free();
}
#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
if (!sys_auth_allowed_user(pw, &loginmsg))
return 0;
#endif
/* We found no reason not to let this user try to log on... */
return 1;
}
void
auth_info(Authctxt *authctxt, const char *fmt, ...)
{
va_list ap;
int i;
free(authctxt->info);
authctxt->info = NULL;
va_start(ap, fmt);
i = vasprintf(&authctxt->info, fmt, ap);
va_end(ap);
if (i < 0 || authctxt->info == NULL)
fatal("vasprintf failed");
}
void
auth_log(Authctxt *authctxt, int authenticated, int partial,
const char *method, const char *submethod)
{
void (*authlog) (const char *fmt,...) = verbose;
char *authmsg;
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
return;
/* Raise logging level */
if (authenticated == 1 ||
!authctxt->valid ||
authctxt->failures >= options.max_authtries / 2 ||
strcmp(method, "password") == 0)
authlog = logit;
if (authctxt->postponed)
authmsg = "Postponed";
else if (partial)
authmsg = "Partial";
else
authmsg = authenticated ? "Accepted" : "Failed";
authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s",
authmsg,
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
get_remote_port(),
compat20 ? "ssh2" : "ssh1",
authctxt->info != NULL ? ": " : "",
authctxt->info != NULL ? authctxt->info : "");
free(authctxt->info);
authctxt->info = NULL;
#ifdef CUSTOM_FAILED_LOGIN
if (authenticated == 0 && !authctxt->postponed &&
(strcmp(method, "password") == 0 ||
strncmp(method, "keyboard-interactive", 20) == 0 ||
strcmp(method, "challenge-response") == 0))
record_failed_login(authctxt->user,
get_canonical_hostname(options.use_dns), "ssh");
# ifdef WITH_AIXAUTHENTICATE
if (authenticated)
sys_auth_record_login(authctxt->user,
get_canonical_hostname(options.use_dns), "ssh", &loginmsg);
# endif
#endif
#ifdef SSH_AUDIT_EVENTS
if (authenticated == 0 && !authctxt->postponed)
audit_event(audit_classify_auth(method));
#endif
}
void
auth_maxtries_exceeded(Authctxt *authctxt)
{
error("maximum authentication attempts exceeded for "
"%s%.100s from %.200s port %d %s",
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
get_remote_port(),
compat20 ? "ssh2" : "ssh1");
packet_disconnect("Too many authentication failures");
/* NOTREACHED */
}
/*
* Check whether root logins are disallowed.
*/
int
auth_root_allowed(const char *method)
{
switch (options.permit_root_login) {
case PERMIT_YES:
return 1;
case PERMIT_NO_PASSWD:
if (strcmp(method, "publickey") == 0 ||
strcmp(method, "hostbased") == 0 ||
strcmp(method, "gssapi-with-mic") == 0)
return 1;
break;
case PERMIT_FORCED_ONLY:
if (forced_command) {
logit("Root login accepted for forced command.");
return 1;
}
break;
}
logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
return 0;
}
/*
* Given a template and a passwd structure, build a filename
* by substituting % tokenised options. Currently, %% becomes '%',
* %h becomes the home directory and %u the username.
*
* This returns a buffer allocated by xmalloc.
*/
char *
expand_authorized_keys(const char *filename, struct passwd *pw)
{
char *file, ret[PATH_MAX];
int i;
file = percent_expand(filename, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL);
/*
* Ensure that filename starts anchored. If not, be backward
* compatible and prepend the '%h/'
*/
if (*file == '/')
return (file);
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
if (i < 0 || (size_t)i >= sizeof(ret))
fatal("expand_authorized_keys: path too long");
free(file);
return (xstrdup(ret));
}
char *
authorized_principals_file(struct passwd *pw)
{
if (options.authorized_principals_file == NULL)
return NULL;
return expand_authorized_keys(options.authorized_principals_file, pw);
}
/* return ok if key exists in sysfile or userfile */
HostStatus
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
const char *sysfile, const char *userfile)
{
char *user_hostfile;
struct stat st;
HostStatus host_status;
struct hostkeys *hostkeys;
const struct hostkey_entry *found;
hostkeys = init_hostkeys();
load_hostkeys(hostkeys, host, sysfile);
if (userfile != NULL) {
user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
logit("Authentication refused for %.100s: "
"bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
auth_debug_add("Ignored %.200s: bad ownership or modes",
user_hostfile);
} else {
temporarily_use_uid(pw);
load_hostkeys(hostkeys, host, user_hostfile);
restore_uid();
}
free(user_hostfile);
}
host_status = check_key_in_hostkeys(hostkeys, key, &found);
if (host_status == HOST_REVOKED)
error("WARNING: revoked key for %s attempted authentication",
found->host);
else if (host_status == HOST_OK)
debug("%s: key for %s found at %s:%ld", __func__,
found->host, found->file, found->line);
else
debug("%s: key for host %s not found", __func__, host);
free_hostkeys(hostkeys);
return host_status;
}
/*
* Check a given path for security. This is defined as all components
* of the path to the file must be owned by either the owner of
* of the file or root and no directories must be group or world writable.
*
* XXX Should any specific check be done for sym links ?
*
* Takes a file name, its stat information (preferably from fstat() to
* avoid races), the uid of the expected owner, their home directory and an
* error buffer plus max size as arguments.
*
* Returns 0 on success and -1 on failure
*/
int
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
uid_t uid, char *err, size_t errlen)
{
char buf[PATH_MAX], homedir[PATH_MAX];
char *cp;
int comparehome = 0;
struct stat st;
if (realpath(name, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", name,
strerror(errno));
return -1;
}
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
comparehome = 1;
if (!S_ISREG(stp->st_mode)) {
snprintf(err, errlen, "%s is not a regular file", buf);
return -1;
}
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
(stp->st_mode & 022) != 0) {
snprintf(err, errlen, "bad ownership or modes for file %s",
buf);
return -1;
}
/* for each component of the canonical path, walking upwards */
for (;;) {
if ((cp = dirname(buf)) == NULL) {
snprintf(err, errlen, "dirname() failed");
return -1;
}
strlcpy(buf, cp, sizeof(buf));
if (stat(buf, &st) < 0 ||
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
snprintf(err, errlen,
"bad ownership or modes for directory %s", buf);
return -1;
}
/* If are past the homedir then we can stop */
if (comparehome && strcmp(homedir, buf) == 0)
break;
/*
* dirname should always complete with a "/" path,
* but we can be paranoid and check for "." too
*/
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
break;
}
return 0;
}
/*
* Version of secure_path() that accepts an open file descriptor to
* avoid races.
*
* Returns 0 on success and -1 on failure
*/
static int
secure_filename(FILE *f, const char *file, struct passwd *pw,
char *err, size_t errlen)
{
struct stat st;
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0) {
snprintf(err, errlen, "cannot stat file %s: %s",
file, strerror(errno));
return -1;
}
return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
}
static FILE *
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int log_missing, char *file_type)
{
char line[1024];
struct stat st;
int fd;
FILE *f;
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
if (log_missing || errno != ENOENT)
debug("Could not open %s '%s': %s", file_type, file,
strerror(errno));
return NULL;
}
if (fstat(fd, &st) < 0) {
close(fd);
return NULL;
}
if (!S_ISREG(st.st_mode)) {
logit("User %s %s %s is not a regular file",
pw->pw_name, file_type, file);
close(fd);
return NULL;
}
unset_nonblock(fd);
if ((f = fdopen(fd, "r")) == NULL) {
close(fd);
return NULL;
}
if (strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
fclose(f);
logit("Authentication refused: %s", line);
auth_debug_add("Ignored %s: %s", file_type, line);
return NULL;
}
return f;
}
FILE *
auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
{
return auth_openfile(file, pw, strict_modes, 1, "authorized keys");
}
FILE *
auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
{
return auth_openfile(file, pw, strict_modes, 0,
"authorized principals");
}
struct passwd *
getpwnamallow(const char *user)
{
#ifdef HAVE_LOGIN_CAP
extern login_cap_t *lc;
#ifdef BSD_AUTH
auth_session_t *as;
#endif
#endif
struct passwd *pw;
struct connection_info *ci = get_connection_info(1, options.use_dns);
ci->user = user;
parse_server_match_config(&options, ci);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user);
#endif
pw = getpwnam(user);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_restoreauthdb();
#endif
#ifdef HAVE_CYGWIN
/*
* Windows usernames are case-insensitive. To avoid later problems
* when trying to match the username, the user is only allowed to
* login if the username is given in the same case as stored in the
* user database.
*/
if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
logit("Login name %.100s does not match stored username %.100s",
user, pw->pw_name);
pw = NULL;
}
#endif
if (pw == NULL) {
logit("Invalid user %.100s from %.100s",
user, get_remote_ipaddr());
#ifdef CUSTOM_FAILED_LOGIN
record_failed_login(user,
get_canonical_hostname(options.use_dns), "ssh");
#endif
#ifdef SSH_AUDIT_EVENTS
audit_event(SSH_INVALID_USER);
#endif /* SSH_AUDIT_EVENTS */
return (NULL);
}
if (!allowed_user(pw))
return (NULL);
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(pw->pw_class)) == NULL) {
debug("unable to get login class: %s", user);
return (NULL);
}
#ifdef BSD_AUTH
if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
debug("Approval failure for %s", user);
pw = NULL;
}
if (as != NULL)
auth_close(as);
#endif
#endif
if (pw != NULL)
return (pwcopy(pw));
return (NULL);
}
/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
int
auth_key_is_revoked(Key *key)
{
char *fp = NULL;
int r;
if (options.revoked_keys_file == NULL)
return 0;
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
error("%s: fingerprint key: %s", __func__, ssh_err(r));
goto out;
}
r = sshkey_check_revoked(key, options.revoked_keys_file);
switch (r) {
case 0:
break; /* not revoked */
case SSH_ERR_KEY_REVOKED:
error("Authentication key %s %s revoked by file %s",
sshkey_type(key), fp, options.revoked_keys_file);
goto out;
default:
error("Error checking authentication key %s %s in "
"revoked keys file %s: %s", sshkey_type(key), fp,
options.revoked_keys_file, ssh_err(r));
goto out;
}
/* Success */
r = 0;
out:
free(fp);
return r == 0 ? 0 : 1;
}
void
auth_debug_add(const char *fmt,...)
{
char buf[1024];
va_list args;
if (!auth_debug_init)
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
buffer_put_cstring(&auth_debug, buf);
}
void
auth_debug_send(void)
{
char *msg;
if (!auth_debug_init)
return;
while (buffer_len(&auth_debug)) {
msg = buffer_get_string(&auth_debug, NULL);
packet_send_debug("%s", msg);
free(msg);
}
}
void
auth_debug_reset(void)
{
if (auth_debug_init)
buffer_clear(&auth_debug);
else {
buffer_init(&auth_debug);
auth_debug_init = 1;
}
}
struct passwd *
fakepw(void)
{
static struct passwd fake;
memset(&fake, 0, sizeof(fake));
fake.pw_name = "NOUSER";
fake.pw_passwd =
"$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
fake.pw_gecos = "NOUSER";
#endif
fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
fake.pw_class = "";
#endif
fake.pw_dir = "/nonexist";
fake.pw_shell = "/nonexist";
return (&fake);
}

229
crypto/external/bsd/openssh/dist/auth.h vendored Normal file
View File

@@ -0,0 +1,229 @@
/* $OpenBSD: auth.h,v 1.84 2015/05/08 06:41:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AUTH_H
#define AUTH_H
#include <signal.h>
#include <openssl/rsa.h>
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
#endif
#ifdef BSD_AUTH
#include <bsd_auth.h>
#endif
#ifdef KRB5
#include <krb5.h>
#endif
struct ssh;
struct sshkey;
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
sig_atomic_t success;
int authenticated; /* authenticated and alarms cancelled */
int postponed; /* authentication needs another step */
int valid; /* user exists and is allowed to login */
int attempt;
int failures;
int server_caused_failure;
int force_pwchange;
char *user; /* username sent by the client */
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
void *kbdintctxt;
char *info; /* Extra info for next auth_log */
#ifdef BSD_AUTH
auth_session_t *as;
#endif
char **auth_methods; /* modified from server config */
u_int num_auth_methods;
#ifdef KRB5
krb5_context krb5_ctx;
krb5_ccache krb5_fwd_ccache;
krb5_principal krb5_user;
char *krb5_ticket_file;
char *krb5_ccname;
#endif
Buffer *loginmsg;
void *methoddata;
struct sshkey **prev_userkeys;
u_int nprev_userkeys;
};
/*
* Every authentication method has to handle authentication requests for
* non-existing users, or for users that are not allowed to login. In this
* case 'valid' is set to 0, but 'user' points to the username requested by
* the client.
*/
struct Authmethod {
char *name;
int (*userauth)(Authctxt *authctxt);
int *enabled;
};
/*
* Keyboard interactive device:
* init_ctx returns: non NULL upon success
* query returns: 0 - success, otherwise failure
* respond returns: 0 - success, 1 - need further interaction,
* otherwise - failure
*/
struct KbdintDevice
{
const char *name;
void* (*init_ctx)(Authctxt*);
int (*query)(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on);
int (*respond)(void *ctx, u_int numresp, char **responses);
void (*free_ctx)(void *ctx);
};
int auth_rhosts(struct passwd *, const char *);
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
int auth_rhosts_rsa(Authctxt *, char *, Key *);
int auth_password(Authctxt *, const char *);
int auth_rsa(Authctxt *, BIGNUM *);
int auth_rsa_challenge_dialog(Key *);
BIGNUM *auth_rsa_generate_challenge(Key *);
int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
int user_key_allowed(struct passwd *, Key *, int);
void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
__attribute__((__format__ (printf, 3, 4)));
void auth2_record_userkey(Authctxt *, struct sshkey *);
int auth2_userkey_already_used(Authctxt *, struct sshkey *);
struct stat;
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
char *, size_t);
#ifdef KRB5
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
int auth_krb5_password(Authctxt *authctxt, const char *password);
void krb5_cleanup_proc(Authctxt *authctxt);
#endif /* KRB5 */
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
#include <shadow.h>
int auth_shadow_acctexpired(struct spwd *);
int auth_shadow_pwexpired(Authctxt *);
#endif
#include "auth-pam.h"
#include "audit.h"
void remove_kbdint_device(const char *);
void disable_forwarding(void);
void do_authentication(Authctxt *);
void do_authentication2(Authctxt *);
void auth_info(Authctxt *authctxt, const char *, ...)
__attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2)));
void auth_log(Authctxt *, int, int, const char *, const char *);
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
void userauth_finish(Authctxt *, int, const char *, const char *);
int auth_root_allowed(const char *);
void userauth_send_banner(const char *);
char *auth2_read_banner(void);
int auth2_methods_valid(const char *, int);
int auth2_update_methods_lists(Authctxt *, const char *, const char *);
int auth2_setup_methods_lists(Authctxt *);
int auth2_method_allowed(Authctxt *, const char *, const char *);
void privsep_challenge_enable(void);
int auth2_challenge(Authctxt *, char *);
void auth2_challenge_stop(Authctxt *);
int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int bsdauth_respond(void *, u_int, char **);
int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int skey_respond(void *, u_int, char **);
int allowed_user(struct passwd *);
struct passwd * getpwnamallow(const char *user);
char *get_challenge(Authctxt *);
int verify_response(Authctxt *, const char *);
void abandon_challenge_response(Authctxt *);
char *expand_authorized_keys(const char *, struct passwd *pw);
char *authorized_principals_file(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
FILE *auth_openprincipals(const char *, struct passwd *, int);
int auth_key_is_revoked(Key *);
HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *,
const char *, const char *);
/* hostkey handling */
Key *get_hostkey_by_index(int);
Key *get_hostkey_public_by_index(int, struct ssh *);
Key *get_hostkey_public_by_type(int, int, struct ssh *);
Key *get_hostkey_private_by_type(int, int, struct ssh *);
int get_hostkey_index(Key *, int, struct ssh *);
int ssh1_session_key(BIGNUM *);
int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *,
const u_char *, size_t, u_int);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void auth_debug_send(void);
void auth_debug_reset(void);
struct passwd *fakepw(void);
int sys_auth_passwd(Authctxt *, const char *);
#define SKEY_PROMPT "\nS/Key Password: "
#if defined(KRB5) && !defined(HEIMDAL)
#include <krb5.h>
krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
#endif
#endif

444
crypto/external/bsd/openssh/dist/auth1.c vendored Normal file
View File

@@ -0,0 +1,444 @@
/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* 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".
*/
#include "includes.h"
#ifdef WITH_SSH1
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "rsa.h"
#include "ssh1.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "channels.h"
#include "session.h"
#include "uidswap.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "buffer.h"
/* import */
extern ServerOptions options;
extern Buffer loginmsg;
static int auth1_process_password(Authctxt *);
static int auth1_process_rsa(Authctxt *);
static int auth1_process_rhosts_rsa(Authctxt *);
static int auth1_process_tis_challenge(Authctxt *);
static int auth1_process_tis_response(Authctxt *);
static char *client_user = NULL; /* Used to fill in remote user for PAM */
struct AuthMethod1 {
int type;
char *name;
int *enabled;
int (*method)(Authctxt *);
};
const struct AuthMethod1 auth1_methods[] = {
{
SSH_CMSG_AUTH_PASSWORD, "password",
&options.password_authentication, auth1_process_password
},
{
SSH_CMSG_AUTH_RSA, "rsa",
&options.rsa_authentication, auth1_process_rsa
},
{
SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
&options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
},
{
SSH_CMSG_AUTH_TIS, "challenge-response",
&options.challenge_response_authentication,
auth1_process_tis_challenge
},
{
SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
&options.challenge_response_authentication,
auth1_process_tis_response
},
{ -1, NULL, NULL, NULL}
};
static const struct AuthMethod1
*lookup_authmethod1(int type)
{
int i;
for (i = 0; auth1_methods[i].name != NULL; i++)
if (auth1_methods[i].type == type)
return (&(auth1_methods[i]));
return (NULL);
}
static char *
get_authname(int type)
{
const struct AuthMethod1 *a;
static char buf[64];
if ((a = lookup_authmethod1(type)) != NULL)
return (a->name);
snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
return (buf);
}
/*ARGSUSED*/
static int
auth1_process_password(Authctxt *authctxt)
{
int authenticated = 0;
char *password;
u_int dlen;
/*
* Read user password. It is in plain text, but was
* transmitted over the encrypted channel so it is
* not visible to an outside observer.
*/
password = packet_get_string(&dlen);
packet_check_eom();
/* Try authentication with the password. */
authenticated = PRIVSEP(auth_password(authctxt, password));
explicit_bzero(password, dlen);
free(password);
return (authenticated);
}
/*ARGSUSED*/
static int
auth1_process_rsa(Authctxt *authctxt)
{
int authenticated = 0;
BIGNUM *n;
/* RSA authentication requested. */
if ((n = BN_new()) == NULL)
fatal("do_authloop: BN_new failed");
packet_get_bignum(n);
packet_check_eom();
authenticated = auth_rsa(authctxt, n);
BN_clear_free(n);
return (authenticated);
}
/*ARGSUSED*/
static int
auth1_process_rhosts_rsa(Authctxt *authctxt)
{
int keybits, authenticated = 0;
u_int bits;
Key *client_host_key;
u_int ulen;
/*
* Get client user name. Note that we just have to
* trust the client; root on the client machine can
* claim to be any user.
*/
client_user = packet_get_cstring(&ulen);
/* Get the client host key. */
client_host_key = key_new(KEY_RSA1);
bits = packet_get_int();
packet_get_bignum(client_host_key->rsa->e);
packet_get_bignum(client_host_key->rsa->n);
keybits = BN_num_bits(client_host_key->rsa->n);
if (keybits < 0 || bits != (u_int)keybits) {
verbose("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d",
BN_num_bits(client_host_key->rsa->n), bits);
}
packet_check_eom();
authenticated = auth_rhosts_rsa(authctxt, client_user,
client_host_key);
key_free(client_host_key);
auth_info(authctxt, "ruser %.100s", client_user);
return (authenticated);
}
/*ARGSUSED*/
static int
auth1_process_tis_challenge(Authctxt *authctxt)
{
char *challenge;
if ((challenge = get_challenge(authctxt)) == NULL)
return (0);
debug("sending challenge '%s'", challenge);
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
packet_put_cstring(challenge);
free(challenge);
packet_send();
packet_write_wait();
return (-1);
}
/*ARGSUSED*/
static int
auth1_process_tis_response(Authctxt *authctxt)
{
int authenticated = 0;
char *response;
u_int dlen;
response = packet_get_string(&dlen);
packet_check_eom();
authenticated = verify_response(authctxt, response);
explicit_bzero(response, dlen);
free(response);
return (authenticated);
}
/*
* read packets, try to authenticate the user and
* return only if authentication is successful
*/
static void
do_authloop(Authctxt *authctxt)
{
int authenticated = 0;
int prev = 0, type = 0;
const struct AuthMethod1 *meth;
debug("Attempting authentication for %s%.100s.",
authctxt->valid ? "" : "invalid user ", authctxt->user);
/* If the user has no password, accept authentication immediately. */
if (options.permit_empty_passwd && options.password_authentication &&
#ifdef KRB5
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
PRIVSEP(auth_password(authctxt, ""))) {
#ifdef USE_PAM
if (options.use_pam && (PRIVSEP(do_pam_account())))
#endif
{
auth_log(authctxt, 1, 0, "without authentication",
NULL);
return;
}
}
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
for (;;) {
/* default to fail */
authenticated = 0;
/* Get a packet from the client. */
prev = type;
type = packet_read();
/*
* If we started challenge-response authentication but the
* next packet is not a response to our challenge, release
* the resources allocated by get_challenge() (which would
* normally have been released by verify_response() had we
* received such a response)
*/
if (prev == SSH_CMSG_AUTH_TIS &&
type != SSH_CMSG_AUTH_TIS_RESPONSE)
abandon_challenge_response(authctxt);
if (authctxt->failures >= options.max_authtries)
goto skip;
if ((meth = lookup_authmethod1(type)) == NULL) {
logit("Unknown message during authentication: "
"type %d", type);
goto skip;
}
if (!*(meth->enabled)) {
verbose("%s authentication disabled.", meth->name);
goto skip;
}
authenticated = meth->method(authctxt);
if (authenticated == -1)
continue; /* "postponed" */
#ifdef BSD_AUTH
if (authctxt->as) {
auth_close(authctxt->as);
authctxt->as = NULL;
}
#endif
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
authctxt->user);
#ifdef _UNICOS
if (authenticated && cray_access_denied(authctxt->user)) {
authenticated = 0;
fatal("Access denied for user %s.",authctxt->user);
}
#endif /* _UNICOS */
#ifndef HAVE_CYGWIN
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(meth->name)) {
authenticated = 0;
# ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
# endif
}
#endif
#ifdef USE_PAM
if (options.use_pam && authenticated &&
!PRIVSEP(do_pam_account())) {
char *msg;
size_t len;
error("Access denied for user %s by PAM account "
"configuration", authctxt->user);
len = buffer_len(&loginmsg);
buffer_append(&loginmsg, "\0", 1);
msg = buffer_ptr(&loginmsg);
/* strip trailing newlines */
if (len > 0)
while (len > 0 && msg[--len] == '\n')
msg[len] = '\0';
else
msg = "Access denied.";
packet_disconnect("%s", msg);
}
#endif
skip:
/* Log before sending the reply */
auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
free(client_user);
client_user = NULL;
if (authenticated)
return;
if (++authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
#endif
auth_maxtries_exceeded(authctxt);
}
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
}
}
/*
* Performs authentication of an incoming connection. Session key has already
* been exchanged and encryption is enabled.
*/
void
do_authentication(Authctxt *authctxt)
{
u_int ulen;
char *user, *style = NULL;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(SSH_CMSG_USER);
/* Get the user name. */
user = packet_get_cstring(&ulen);
packet_check_eom();
if ((style = strchr(user, ':')) != NULL)
*style++ = '\0';
authctxt->user = user;
authctxt->style = style;
/* Verify that the user is a valid user. */
if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
authctxt->valid = 1;
else {
debug("do_authentication: invalid user %s", user);
authctxt->pw = fakepw();
}
/* Configuration may have changed as a result of Match */
if (options.num_auth_methods != 0)
fatal("AuthenticationMethods is not supported with SSH "
"protocol 1");
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
#ifdef USE_PAM
if (options.use_pam)
PRIVSEP(start_pam(authctxt));
#endif
/*
* If we are not running as root, the user must have the same uid as
* the server.
*/
#ifndef HAVE_CYGWIN
if (!use_privsep && getuid() != 0 && authctxt->pw &&
authctxt->pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
#endif
/*
* Loop until the user has been authenticated or the connection is
* closed, do_authloop() returns only if authentication is successful
*/
do_authloop(authctxt);
/* The user has been authenticated and accepted. */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
}
#endif /* WITH_SSH1 */

View File

@@ -0,0 +1,381 @@
/* $OpenBSD: auth2-chall.c,v 1.43 2015/07/18 07:57:14 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Per Allansson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "xmalloc.h"
#include "ssh2.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "buffer.h"
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
/* import */
extern ServerOptions options;
static int auth2_challenge_start(Authctxt *);
static int send_userauth_info_request(Authctxt *);
static int input_userauth_info_response(int, u_int32_t, void *);
#ifdef BSD_AUTH
extern KbdintDevice bsdauth_device;
#else
#ifdef USE_PAM
extern KbdintDevice sshpam_device;
#endif
#ifdef SKEY
extern KbdintDevice skey_device;
#endif
#endif
KbdintDevice *devices[] = {
#ifdef BSD_AUTH
&bsdauth_device,
#else
#ifdef USE_PAM
&sshpam_device,
#endif
#ifdef SKEY
&skey_device,
#endif
#endif
NULL
};
typedef struct KbdintAuthctxt KbdintAuthctxt;
struct KbdintAuthctxt
{
char *devices;
void *ctxt;
KbdintDevice *device;
u_int nreq;
u_int devices_done;
};
#ifdef USE_PAM
void
remove_kbdint_device(const char *devname)
{
int i, j;
for (i = 0; devices[i] != NULL; i++)
if (strcmp(devices[i]->name, devname) == 0) {
for (j = i; devices[j] != NULL; j++)
devices[j] = devices[j+1];
i--;
}
}
#endif
static KbdintAuthctxt *
kbdint_alloc(const char *devs)
{
KbdintAuthctxt *kbdintctxt;
Buffer b;
int i;
#ifdef USE_PAM
if (!options.use_pam)
remove_kbdint_device("pam");
#endif
kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt));
if (strcmp(devs, "") == 0) {
buffer_init(&b);
for (i = 0; devices[i]; i++) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, devices[i]->name,
strlen(devices[i]->name));
}
buffer_append(&b, "\0", 1);
kbdintctxt->devices = xstrdup(buffer_ptr(&b));
buffer_free(&b);
} else {
kbdintctxt->devices = xstrdup(devs);
}
debug("kbdint_alloc: devices '%s'", kbdintctxt->devices);
kbdintctxt->ctxt = NULL;
kbdintctxt->device = NULL;
kbdintctxt->nreq = 0;
return kbdintctxt;
}
static void
kbdint_reset_device(KbdintAuthctxt *kbdintctxt)
{
if (kbdintctxt->ctxt) {
kbdintctxt->device->free_ctx(kbdintctxt->ctxt);
kbdintctxt->ctxt = NULL;
}
kbdintctxt->device = NULL;
}
static void
kbdint_free(KbdintAuthctxt *kbdintctxt)
{
if (kbdintctxt->device)
kbdint_reset_device(kbdintctxt);
free(kbdintctxt->devices);
explicit_bzero(kbdintctxt, sizeof(*kbdintctxt));
free(kbdintctxt);
}
/* get next device */
static int
kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
{
size_t len;
char *t;
int i;
if (kbdintctxt->device)
kbdint_reset_device(kbdintctxt);
do {
len = kbdintctxt->devices ?
strcspn(kbdintctxt->devices, ",") : 0;
if (len == 0)
break;
for (i = 0; devices[i]; i++) {
if ((kbdintctxt->devices_done & (1 << i)) != 0 ||
!auth2_method_allowed(authctxt,
"keyboard-interactive", devices[i]->name))
continue;
if (strncmp(kbdintctxt->devices, devices[i]->name,
len) == 0) {
kbdintctxt->device = devices[i];
kbdintctxt->devices_done |= 1 << i;
}
}
t = kbdintctxt->devices;
kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
free(t);
debug2("kbdint_next_device: devices %s", kbdintctxt->devices ?
kbdintctxt->devices : "<empty>");
} while (kbdintctxt->devices && !kbdintctxt->device);
return kbdintctxt->device ? 1 : 0;
}
/*
* try challenge-response, set authctxt->postponed if we have to
* wait for the response.
*/
int
auth2_challenge(Authctxt *authctxt, char *devs)
{
debug("auth2_challenge: user=%s devs=%s",
authctxt->user ? authctxt->user : "<nouser>",
devs ? devs : "<no devs>");
if (authctxt->user == NULL || !devs)
return 0;
if (authctxt->kbdintctxt == NULL)
authctxt->kbdintctxt = kbdint_alloc(devs);
return auth2_challenge_start(authctxt);
}
/* unregister kbd-int callbacks and context */
void
auth2_challenge_stop(Authctxt *authctxt)
{
/* unregister callback */
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
if (authctxt->kbdintctxt != NULL) {
kbdint_free(authctxt->kbdintctxt);
authctxt->kbdintctxt = NULL;
}
}
/* side effect: sets authctxt->postponed if a reply was sent*/
static int
auth2_challenge_start(Authctxt *authctxt)
{
KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt;
debug2("auth2_challenge_start: devices %s",
kbdintctxt->devices ? kbdintctxt->devices : "<empty>");
if (kbdint_next_device(authctxt, kbdintctxt) == 0) {
auth2_challenge_stop(authctxt);
return 0;
}
debug("auth2_challenge_start: trying authentication method '%s'",
kbdintctxt->device->name);
if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) {
auth2_challenge_stop(authctxt);
return 0;
}
if (send_userauth_info_request(authctxt) == 0) {
auth2_challenge_stop(authctxt);
return 0;
}
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
&input_userauth_info_response);
authctxt->postponed = 1;
return 0;
}
static int
send_userauth_info_request(Authctxt *authctxt)
{
KbdintAuthctxt *kbdintctxt;
char *name, *instr, **prompts;
u_int i, *echo_on;
kbdintctxt = authctxt->kbdintctxt;
if (kbdintctxt->device->query(kbdintctxt->ctxt,
&name, &instr, &kbdintctxt->nreq, &prompts, &echo_on))
return 0;
packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
packet_put_cstring(name);
packet_put_cstring(instr);
packet_put_cstring(""); /* language not used */
packet_put_int(kbdintctxt->nreq);
for (i = 0; i < kbdintctxt->nreq; i++) {
packet_put_cstring(prompts[i]);
packet_put_char(echo_on[i]);
}
packet_send();
packet_write_wait();
for (i = 0; i < kbdintctxt->nreq; i++)
free(prompts[i]);
free(prompts);
free(echo_on);
free(name);
free(instr);
return 1;
}
static int
input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
KbdintAuthctxt *kbdintctxt;
int authenticated = 0, res;
u_int i, nresp;
const char *devicename = NULL;
char **response = NULL;
if (authctxt == NULL)
fatal("input_userauth_info_response: no authctxt");
kbdintctxt = authctxt->kbdintctxt;
if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL)
fatal("input_userauth_info_response: no kbdintctxt");
if (kbdintctxt->device == NULL)
fatal("input_userauth_info_response: no device");
authctxt->postponed = 0; /* reset */
nresp = packet_get_int();
if (nresp != kbdintctxt->nreq)
fatal("input_userauth_info_response: wrong number of replies");
if (nresp > 100)
fatal("input_userauth_info_response: too many replies");
if (nresp > 0) {
response = xcalloc(nresp, sizeof(char *));
for (i = 0; i < nresp; i++)
response[i] = packet_get_string(NULL);
}
packet_check_eom();
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);
for (i = 0; i < nresp; i++) {
explicit_bzero(response[i], strlen(response[i]));
free(response[i]);
}
free(response);
switch (res) {
case 0:
/* Success! */
authenticated = authctxt->valid ? 1 : 0;
break;
case 1:
/* Authentication needs further interaction */
if (send_userauth_info_request(authctxt) == 1)
authctxt->postponed = 1;
break;
default:
/* Failure! */
break;
}
devicename = kbdintctxt->device->name;
if (!authctxt->postponed) {
if (authenticated) {
auth2_challenge_stop(authctxt);
} else {
/* start next device */
/* may set authctxt->postponed */
auth2_challenge_start(authctxt);
}
}
userauth_finish(authctxt, authenticated, "keyboard-interactive",
devicename);
return 0;
}
void
privsep_challenge_enable(void)
{
#if defined(BSD_AUTH) || defined(USE_PAM) || defined(SKEY)
int n = 0;
#endif
#ifdef BSD_AUTH
extern KbdintDevice mm_bsdauth_device;
#endif
#ifdef USE_PAM
extern KbdintDevice mm_sshpam_device;
#endif
#ifdef SKEY
extern KbdintDevice mm_skey_device;
#endif
#ifdef BSD_AUTH
devices[n++] = &mm_bsdauth_device;
#else
#ifdef USE_PAM
devices[n++] = &mm_sshpam_device;
#endif
#ifdef SKEY
devices[n++] = &mm_skey_device;
#endif
#endif
}

View File

@@ -0,0 +1,299 @@
/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef GSSAPI
#include <sys/types.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "ssh2.h"
#include "log.h"
#include "dispatch.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "packet.h"
#include "ssh-gss.h"
#include "monitor_wrap.h"
extern ServerOptions options;
static int input_gssapi_token(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_errtok(int, u_int32_t, void *);
/*
* We only support those mechanisms that we know about (ie ones that we know
* how to check local user kuserok and the like)
*/
static int
userauth_gssapi(Authctxt *authctxt)
{
gss_OID_desc goid = {0, NULL};
Gssctxt *ctxt = NULL;
int mechs;
int present;
OM_uint32 ms;
u_int len;
u_char *doid = NULL;
if (!authctxt->valid || authctxt->user == NULL)
return (0);
mechs = packet_get_int();
if (mechs == 0) {
debug("Mechanism negotiation is not supported");
return (0);
}
do {
mechs--;
free(doid);
present = 0;
doid = packet_get_string(&len);
if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
doid[1] == len - 2) {
goid.elements = doid + 2;
goid.length = len - 2;
ssh_gssapi_test_oid_supported(&ms, &goid, &present);
} else {
logit("Badly formed OID received");
}
} while (mechs > 0 && !present);
if (!present) {
free(doid);
authctxt->server_caused_failure = 1;
return (0);
}
if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
if (ctxt != NULL)
ssh_gssapi_delete_ctx(&ctxt);
free(doid);
authctxt->server_caused_failure = 1;
return (0);
}
authctxt->methoddata = (void *)ctxt;
packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
/* Return the OID that we received */
packet_put_string(doid, len);
packet_send();
free(doid);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
authctxt->postponed = 1;
return (0);
}
static int
input_gssapi_token(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
Gssctxt *gssctxt;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc recv_tok;
OM_uint32 maj_status, min_status, flags;
u_int len;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
recv_tok.value = packet_get_string(&len);
recv_tok.length = len; /* u_int vs. size_t */
packet_check_eom();
maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
&send_tok, &flags));
free(recv_tok.value);
if (GSS_ERROR(maj_status)) {
if (send_tok.length != 0) {
packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
packet_put_string(send_tok.value, send_tok.length);
packet_send();
}
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
} else {
if (send_tok.length != 0) {
packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
packet_put_string(send_tok.value, send_tok.length);
packet_send();
}
if (maj_status == GSS_S_COMPLETE) {
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
if (flags & GSS_C_INTEG_FLAG)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
&input_gssapi_mic);
else
dispatch_set(
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
&input_gssapi_exchange_complete);
}
}
gss_release_buffer(&min_status, &send_tok);
return 0;
}
static int
input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
Gssctxt *gssctxt;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc recv_tok;
OM_uint32 maj_status;
u_int len;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
recv_tok.value = packet_get_string(&len);
recv_tok.length = len;
packet_check_eom();
/* Push the error token into GSSAPI to see what it says */
maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
&send_tok, NULL));
free(recv_tok.value);
/* We can't return anything to the client, even if we wanted to */
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
/* The client will have already moved on to the next auth */
gss_release_buffer(&maj_status, &send_tok);
return 0;
}
/*
* This is called when the client thinks we've completed authentication.
* It should only be enabled in the dispatch handler by the function above,
* which only enables it once the GSSAPI exchange is complete.
*/
static int
input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
int authenticated;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
/*
* We don't need to check the status, because we're only enabled in
* the dispatcher once the exchange is complete
*/
packet_check_eom();
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
return 0;
}
static int
input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
Gssctxt *gssctxt;
int authenticated = 0;
Buffer b;
gss_buffer_desc mic, gssbuf;
u_int len;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
mic.value = packet_get_string(&len);
mic.length = len;
ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
"gssapi-with-mic");
gssbuf.value = buffer_ptr(&b);
gssbuf.length = buffer_len(&b);
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
else
logit("GSSAPI MIC check failed");
buffer_free(&b);
free(mic.value);
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
return 0;
}
Authmethod method_gssapi = {
"gssapi-with-mic",
userauth_gssapi,
&options.gss_authentication
};
#endif /* GSSAPI */

View File

@@ -0,0 +1,250 @@
/* $OpenBSD: auth2-hostbased.c,v 1.25 2015/05/04 06:10:48 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "canohost.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "pathnames.h"
#include "match.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
static int
userauth_hostbased(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg, *cuser, *chost, *service;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_hostbased: disabled because of invalid user");
return 0;
}
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
chost = packet_get_string(NULL);
cuser = packet_get_string(NULL);
sig = packet_get_string(&slen);
debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
buffer_init(&b);
buffer_append(&b, sig, slen);
buffer_dump(&b);
buffer_free(&b);
#endif
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
logit("userauth_hostbased: unsupported "
"public key algorithm: %s", pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_hostbased: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_hostbased: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
if (key_type_plain(key->type) == KEY_RSA &&
(datafellows & SSH_BUG_RSASIGMD5) != 0) {
error("Refusing RSA key because peer uses unsafe "
"signature format");
goto done;
}
if (match_pattern_list(sshkey_ssh_name(key),
options.hostbased_key_types, 0) != 1) {
logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
__func__, sshkey_type(key));
goto done;
}
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
buffer_put_string(&b, session_id2, session_id2_len);
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b, service);
buffer_put_cstring(&b, "hostbased");
buffer_put_string(&b, pkalg, alen);
buffer_put_string(&b, pkblob, blen);
buffer_put_cstring(&b, chost);
buffer_put_cstring(&b, cuser);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
pubkey_auth_info(authctxt, key,
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
/* test for allowed key and correct signature */
authenticated = 0;
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
buffer_free(&b);
done:
debug2("userauth_hostbased: authenticated %d", authenticated);
if (key != NULL)
key_free(key);
free(pkalg);
free(pkblob);
free(cuser);
free(chost);
free(sig);
return authenticated;
}
/* return 1 if given hostkey is allowed */
int
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
Key *key)
{
const char *resolvedname, *ipaddr, *lookup, *reason;
HostStatus host_status;
int len;
char *fp;
if (auth_key_is_revoked(key))
return 0;
resolvedname = get_canonical_hostname(options.use_dns);
ipaddr = get_remote_ipaddr();
debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
chost, resolvedname, ipaddr);
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
debug2("stripping trailing dot from chost %s", chost);
chost[len - 1] = '\0';
}
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0) {
debug2("%s: auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" (from packet)",
__func__, cuser, chost);
return 0;
}
lookup = chost;
} else {
if (strcasecmp(resolvedname, chost) != 0)
logit("userauth_hostbased mismatch: "
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) {
debug2("%s: auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" addr \"%.100s\"",
__func__, cuser, resolvedname, ipaddr);
return 0;
}
lookup = resolvedname;
}
debug2("%s: access allowed by auth_rhosts2", __func__);
if (key_is_cert(key) &&
key_cert_check_authority(key, 1, 0, lookup, &reason)) {
error("%s", reason);
auth_debug_add("%s", reason);
return 0;
}
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
/* backward compat if no key has been found. */
if (host_status == HOST_NEW) {
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
}
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
if ((fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
key_type(key->cert->signature_key), fp,
cuser, lookup);
} else {
if ((fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted %s public key %s from %s@%s",
key_type(key), fp, cuser, lookup);
}
free(fp);
}
return (host_status == HOST_OK);
}
Authmethod method_hostbased = {
"hostbased",
userauth_hostbased,
&options.hostbased_authentication
};

View File

@@ -0,0 +1,69 @@
/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "packet.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
/* import */
extern ServerOptions options;
static int
userauth_kbdint(Authctxt *authctxt)
{
int authenticated = 0;
char *lang, *devs;
lang = packet_get_string(NULL);
devs = packet_get_string(NULL);
packet_check_eom();
debug("keyboard-interactive devs %s", devs);
if (options.challenge_response_authentication)
authenticated = auth2_challenge(authctxt, devs);
free(devs);
free(lang);
return authenticated;
}
Authmethod method_kbdint = {
"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication
};

View File

@@ -0,0 +1,77 @@
/* $NetBSD: auth2-krb5.c,v 1.4 2015/04/03 23:58:19 christos Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
__RCSID("$NetBSD: auth2-krb5.c,v 1.4 2015/04/03 23:58:19 christos Exp $");
#include <krb5.h>
#include <stdio.h>
#include "ssh2.h"
#include "xmalloc.h"
#include "packet.h"
#include "log.h"
#include "key.h"
#include "buffer.h"
#include "hostfile.h"
#include "auth.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "misc.h"
#include "servconf.h"
/* import */
extern ServerOptions options;
static int
userauth_kerberos(Authctxt *authctxt)
{
krb5_data tkt, reply;
u_int dlen;
char *client = NULL;
int authenticated = 0;
tkt.data = packet_get_string(&dlen);
tkt.length = dlen;
packet_check_eom();
if (PRIVSEP(auth_krb5(authctxt, &tkt, &client, &reply))) {
authenticated = 1;
if (reply.length)
free(reply.data);
}
if (client)
free(client);
free(tkt.data);
return (authenticated);
}
Authmethod method_kerberos = {
"kerberos-2@ssh.com",
userauth_kerberos,
&options.kerberos_authentication
};

View File

@@ -0,0 +1,75 @@
/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include "atomicio.h"
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "ssh2.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
/* "none" is allowed only one time */
static int none_enabled = 1;
static int
userauth_none(Authctxt *authctxt)
{
none_enabled = 0;
packet_check_eom();
if (options.permit_empty_passwd && options.password_authentication)
return (PRIVSEP(auth_password(authctxt, "")));
return (0);
}
Authmethod method_none = {
"none",
userauth_none,
&none_enabled
};

View File

@@ -0,0 +1,81 @@
/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "packet.h"
#include "log.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "buffer.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "misc.h"
#include "servconf.h"
/* import */
extern ServerOptions options;
static int
userauth_passwd(Authctxt *authctxt)
{
char *password, *newpass;
int authenticated = 0;
int change;
u_int len, newlen;
change = packet_get_char();
password = packet_get_string(&len);
if (change) {
/* discard new password from packet */
newpass = packet_get_string(&newlen);
explicit_bzero(newpass, newlen);
free(newpass);
}
packet_check_eom();
if (change)
logit("password change not supported");
else if (PRIVSEP(auth_password(authctxt, password)) == 1)
authenticated = 1;
explicit_bzero(password, len);
free(password);
return authenticated;
}
Authmethod method_passwd = {
"password",
userauth_passwd,
&options.password_authentication
};

File diff suppressed because it is too large Load Diff

619
crypto/external/bsd/openssh/dist/auth2.c vendored Normal file
View File

@@ -0,0 +1,619 @@
/* $OpenBSD: auth2.c,v 1.135 2015/01/19 20:07:45 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include "atomicio.h"
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "dispatch.h"
#include "pathnames.h"
#include "buffer.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
extern Buffer loginmsg;
/* methods */
extern Authmethod method_none;
extern Authmethod method_pubkey;
extern Authmethod method_passwd;
extern Authmethod method_kbdint;
extern Authmethod method_hostbased;
#ifdef GSSAPI
extern Authmethod method_gssapi;
#endif
Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
#ifdef GSSAPI
&method_gssapi,
#endif
&method_passwd,
&method_kbdint,
&method_hostbased,
NULL
};
/* protocol */
static int input_service_request(int, u_int32_t, void *);
static int input_userauth_request(int, u_int32_t, void *);
/* helper */
static Authmethod *authmethod_lookup(Authctxt *, const char *);
static char *authmethods_get(Authctxt *authctxt);
#define MATCH_NONE 0 /* method or submethod mismatch */
#define MATCH_METHOD 1 /* method matches (no submethod specified) */
#define MATCH_BOTH 2 /* method and submethod match */
#define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */
static int list_starts_with(const char *, const char *, const char *);
char *
auth2_read_banner(void)
{
struct stat st;
char *banner = NULL;
size_t len, n;
int fd;
if ((fd = open(options.banner, O_RDONLY)) == -1)
return (NULL);
if (fstat(fd, &st) == -1) {
close(fd);
return (NULL);
}
if (st.st_size <= 0 || st.st_size > 1*1024*1024) {
close(fd);
return (NULL);
}
len = (size_t)st.st_size; /* truncate */
banner = xmalloc(len + 1);
n = atomicio(read, fd, banner, len);
close(fd);
if (n != len) {
free(banner);
return (NULL);
}
banner[n] = '\0';
return (banner);
}
void
userauth_send_banner(const char *msg)
{
if (datafellows & SSH_BUG_BANNER)
return;
packet_start(SSH2_MSG_USERAUTH_BANNER);
packet_put_cstring(msg);
packet_put_cstring(""); /* language, unused */
packet_send();
debug("%s: sent", __func__);
}
static void
userauth_banner(void)
{
char *banner = NULL;
if (options.banner == NULL || (datafellows & SSH_BUG_BANNER) != 0)
return;
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
goto done;
userauth_send_banner(banner);
done:
free(banner);
}
/*
* loop until authctxt->success == TRUE
*/
void
do_authentication2(Authctxt *authctxt)
{
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
}
/*ARGSUSED*/
static int
input_service_request(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
u_int len;
int acceptit = 0;
char *service = packet_get_cstring(&len);
packet_check_eom();
if (authctxt == NULL)
fatal("input_service_request: no authctxt");
if (strcmp(service, "ssh-userauth") == 0) {
if (!authctxt->success) {
acceptit = 1;
/* now we can handle user-auth requests */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
}
}
/* XXX all other service requests are denied */
if (acceptit) {
packet_start(SSH2_MSG_SERVICE_ACCEPT);
packet_put_cstring(service);
packet_send();
packet_write_wait();
} else {
debug("bad service request %s", service);
packet_disconnect("bad service request %s", service);
}
free(service);
return 0;
}
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
Authmethod *m = NULL;
char *user, *service, *method, *style = NULL;
int authenticated = 0;
if (authctxt == NULL)
fatal("input_userauth_request: no authctxt");
user = packet_get_cstring(NULL);
service = packet_get_cstring(NULL);
method = packet_get_cstring(NULL);
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
if (authctxt->attempt++ == 0) {
/* setup auth context */
authctxt->pw = PRIVSEP(getpwnamallow(user));
authctxt->user = xstrdup(user);
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
} else {
logit("input_userauth_request: invalid user %s", user);
authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_INVALID_USER));
#endif
}
#ifdef USE_PAM
if (options.use_pam)
PRIVSEP(start_pam(authctxt));
#endif
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
if (use_privsep)
mm_inform_authserv(service, style);
userauth_banner();
if (auth2_setup_methods_lists(authctxt) != 0)
packet_disconnect("no authentication methods enabled");
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
"(%s,%s) -> (%s,%s)",
authctxt->user, authctxt->service, user, service);
}
/* reset state */
auth2_challenge_stop(authctxt);
#ifdef GSSAPI
/* XXX move to auth2_gssapi_stop() */
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif
authctxt->postponed = 0;
authctxt->server_caused_failure = 0;
/* try to authenticate user */
m = authmethod_lookup(authctxt, method);
if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(authctxt);
}
userauth_finish(authctxt, authenticated, method, NULL);
free(service);
free(user);
free(method);
return 0;
}
void
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
const char *submethod)
{
char *methods;
int partial = 0;
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
authctxt->user);
if (authenticated && authctxt->postponed)
fatal("INTERNAL ERROR: authenticated and postponed");
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(method)) {
authenticated = 0;
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
#endif
}
if (authenticated && options.num_auth_methods != 0) {
if (!auth2_update_methods_lists(authctxt, method, submethod)) {
authenticated = 0;
partial = 1;
}
}
/* Log before sending the reply */
auth_log(authctxt, authenticated, partial, method, submethod);
if (authctxt->postponed)
return;
#ifdef USE_PAM
if (options.use_pam && authenticated) {
if (!PRIVSEP(do_pam_account())) {
/* if PAM returned a message, send it to the user */
if (buffer_len(&loginmsg) > 0) {
buffer_append(&loginmsg, "\0", 1);
userauth_send_banner(buffer_ptr(&loginmsg));
packet_write_wait();
}
fatal("Access denied for user %s by PAM account "
"configuration", authctxt->user);
}
}
#endif
#ifdef _UNICOS
if (authenticated && cray_access_denied(authctxt->user)) {
authenticated = 0;
fatal("Access denied for user %s.", authctxt->user);
}
#endif /* _UNICOS */
if (authenticated == 1) {
/* turn off userauth */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
packet_start(SSH2_MSG_USERAUTH_SUCCESS);
packet_send();
packet_write_wait();
/* now we can break out */
authctxt->success = 1;
} else {
/* Allow initial try of "none" auth without failure penalty */
if (!partial && !authctxt->server_caused_failure &&
(authctxt->attempt > 1 || strcmp(method, "none") != 0))
authctxt->failures++;
if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
#endif
auth_maxtries_exceeded(authctxt);
}
methods = authmethods_get(authctxt);
debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
partial, methods);
packet_start(SSH2_MSG_USERAUTH_FAILURE);
packet_put_cstring(methods);
packet_put_char(partial);
packet_send();
packet_write_wait();
free(methods);
}
}
/*
* Checks whether method is allowed by at least one AuthenticationMethods
* methods list. Returns 1 if allowed, or no methods lists configured.
* 0 otherwise.
*/
int
auth2_method_allowed(Authctxt *authctxt, const char *method,
const char *submethod)
{
u_int i;
/*
* NB. authctxt->num_auth_methods might be zero as a result of
* auth2_setup_methods_lists(), so check the configuration.
*/
if (options.num_auth_methods == 0)
return 1;
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (list_starts_with(authctxt->auth_methods[i], method,
submethod) != MATCH_NONE)
return 1;
}
return 0;
}
static char *
authmethods_get(Authctxt *authctxt)
{
Buffer b;
char *list;
u_int i;
buffer_init(&b);
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0)
continue;
if (!auth2_method_allowed(authctxt, authmethods[i]->name,
NULL))
continue;
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
buffer_append(&b, "\0", 1);
list = xstrdup(buffer_ptr(&b));
buffer_free(&b);
return list;
}
static Authmethod *
authmethod_lookup(Authctxt *authctxt, const char *name)
{
int i;
if (name != NULL)
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
strcmp(name, authmethods[i]->name) == 0 &&
auth2_method_allowed(authctxt,
authmethods[i]->name, NULL))
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
/*
* Check a comma-separated list of methods for validity. Is need_enable is
* non-zero, then also require that the methods are enabled.
* Returns 0 on success or -1 if the methods list is invalid.
*/
int
auth2_methods_valid(const char *_methods, int need_enable)
{
char *methods, *omethods, *method, *p;
u_int i, found;
int ret = -1;
if (*_methods == '\0') {
error("empty authentication method list");
return -1;
}
omethods = methods = xstrdup(_methods);
while ((method = strsep(&methods, ",")) != NULL) {
for (found = i = 0; !found && authmethods[i] != NULL; i++) {
if ((p = strchr(method, ':')) != NULL)
*p = '\0';
if (strcmp(method, authmethods[i]->name) != 0)
continue;
if (need_enable) {
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0) {
error("Disabled method \"%s\" in "
"AuthenticationMethods list \"%s\"",
method, _methods);
goto out;
}
}
found = 1;
break;
}
if (!found) {
error("Unknown authentication method \"%s\" in list",
method);
goto out;
}
}
ret = 0;
out:
free(omethods);
return ret;
}
/*
* Prune the AuthenticationMethods supplied in the configuration, removing
* any methods lists that include disabled methods. Note that this might
* leave authctxt->num_auth_methods == 0, even when multiple required auth
* has been requested. For this reason, all tests for whether multiple is
* enabled should consult options.num_auth_methods directly.
*/
int
auth2_setup_methods_lists(Authctxt *authctxt)
{
u_int i;
if (options.num_auth_methods == 0)
return 0;
debug3("%s: checking methods", __func__);
authctxt->auth_methods = xcalloc(options.num_auth_methods,
sizeof(*authctxt->auth_methods));
authctxt->num_auth_methods = 0;
for (i = 0; i < options.num_auth_methods; i++) {
if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
logit("Authentication methods list \"%s\" contains "
"disabled method, skipping",
options.auth_methods[i]);
continue;
}
debug("authentication methods list %d: %s",
authctxt->num_auth_methods, options.auth_methods[i]);
authctxt->auth_methods[authctxt->num_auth_methods++] =
xstrdup(options.auth_methods[i]);
}
if (authctxt->num_auth_methods == 0) {
error("No AuthenticationMethods left after eliminating "
"disabled methods");
return -1;
}
return 0;
}
static int
list_starts_with(const char *methods, const char *method,
const char *submethod)
{
size_t l = strlen(method);
int match;
const char *p;
if (strncmp(methods, method, l) != 0)
return MATCH_NONE;
p = methods + l;
match = MATCH_METHOD;
if (*p == ':') {
if (!submethod)
return MATCH_PARTIAL;
l = strlen(submethod);
p += 1;
if (strncmp(submethod, p, l))
return MATCH_NONE;
p += l;
match = MATCH_BOTH;
}
if (*p != ',' && *p != '\0')
return MATCH_NONE;
return match;
}
/*
* Remove method from the start of a comma-separated list of methods.
* Returns 0 if the list of methods did not start with that method or 1
* if it did.
*/
static int
remove_method(char **methods, const char *method, const char *submethod)
{
char *omethods = *methods, *p;
size_t l = strlen(method);
int match;
match = list_starts_with(omethods, method, submethod);
if (match != MATCH_METHOD && match != MATCH_BOTH)
return 0;
p = omethods + l;
if (submethod && match == MATCH_BOTH)
p += 1 + strlen(submethod); /* include colon */
if (*p == ',')
p++;
*methods = xstrdup(p);
free(omethods);
return 1;
}
/*
* Called after successful authentication. Will remove the successful method
* from the start of each list in which it occurs. If it was the last method
* in any list, then authentication is deemed successful.
* Returns 1 if the method completed any authentication list or 0 otherwise.
*/
int
auth2_update_methods_lists(Authctxt *authctxt, const char *method,
const char *submethod)
{
u_int i, found = 0;
debug3("%s: updating methods list after \"%s\"", __func__, method);
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (!remove_method(&(authctxt->auth_methods[i]), method,
submethod))
continue;
found = 1;
if (*authctxt->auth_methods[i] == '\0') {
debug2("authentication methods list %d complete", i);
return 1;
}
debug3("authentication methods list %d remaining: \"%s\"",
i, authctxt->auth_methods[i]);
}
/* This should not happen, but would be bad if it did */
if (!found)
fatal("%s: method not in AuthenticationMethods", __func__);
return 0;
}

View File

@@ -0,0 +1,707 @@
/* $OpenBSD: authfd.c,v 1.98 2015/07/03 03:43:18 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for connecting the local authentication agent.
*
* 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".
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "xmalloc.h"
#include "ssh.h"
#include "rsa.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "authfd.h"
#include "cipher.h"
#include "compat.h"
#include "log.h"
#include "atomicio.h"
#include "misc.h"
#include "ssherr.h"
#define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */
#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */
/* macro to check for "agent failure" message */
#define agent_failed(x) \
((x == SSH_AGENT_FAILURE) || \
(x == SSH_COM_AGENT2_FAILURE) || \
(x == SSH2_AGENT_FAILURE))
/* Convert success/failure response from agent to a err.h status */
static int
decode_reply(u_char type)
{
if (agent_failed(type))
return SSH_ERR_AGENT_FAILURE;
else if (type == SSH_AGENT_SUCCESS)
return 0;
else
return SSH_ERR_INVALID_FORMAT;
}
/* Returns the number of the authentication fd, or -1 if there is none. */
int
ssh_get_authentication_socket(int *fdp)
{
const char *authsocket;
int sock, oerrno;
struct sockaddr_un sunaddr;
if (fdp != NULL)
*fdp = -1;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
if (!authsocket)
return SSH_ERR_AGENT_NOT_PRESENT;
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return SSH_ERR_SYSTEM_ERROR;
/* close on exec */
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 ||
connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
oerrno = errno;
close(sock);
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
if (fdp != NULL)
*fdp = sock;
else
close(sock);
return 0;
}
/* Communicate with agent: send request and read reply */
static int
ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
{
int r;
size_t l, len;
char buf[1024];
/* Get the length of the message, and format it in the buffer. */
len = sshbuf_len(request);
put_u32(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(vwrite, sock, buf, 4) != 4 ||
atomicio(vwrite, sock, (u_char *)sshbuf_ptr(request),
sshbuf_len(request)) != sshbuf_len(request))
return SSH_ERR_AGENT_COMMUNICATION;
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
if (atomicio(read, sock, buf, 4) != 4)
return SSH_ERR_AGENT_COMMUNICATION;
/* Extract the length, and check it for sanity. */
len = get_u32(buf);
if (len > MAX_AGENT_REPLY_LEN)
return SSH_ERR_INVALID_FORMAT;
/* Read the rest of the response in to the buffer. */
sshbuf_reset(reply);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
if (atomicio(read, sock, buf, l) != l)
return SSH_ERR_AGENT_COMMUNICATION;
if ((r = sshbuf_put(reply, buf, l)) != 0)
return r;
len -= l;
}
return 0;
}
/*
* Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by
* ssh_get_authentication_socket().
*/
void
ssh_close_authentication_socket(int sock)
{
if (getenv(SSH_AUTHSOCKET_ENV_NAME))
close(sock);
}
/* Lock/unlock agent */
int
ssh_lock_agent(int sock, int lock, const char *password)
{
int r;
u_char type = lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK;
struct sshbuf *msg;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshbuf_put_cstring(msg, password)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
#ifdef WITH_SSH1
static int
deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
{
struct sshkey *key;
int r, keybits;
u_int32_t bits;
char *comment = NULL;
if ((key = sshkey_new(KEY_RSA1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_u32(ids, &bits)) != 0 ||
(r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 ||
(r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 ||
(r = sshbuf_get_cstring(ids, &comment, NULL)) != 0)
goto out;
keybits = BN_num_bits(key->rsa->n);
/* XXX previously we just warned here. I think we should be strict */
if (keybits < 0 || bits != (u_int)keybits) {
r = SSH_ERR_KEY_BITS_MISMATCH;
goto out;
}
if (keyp != NULL) {
*keyp = key;
key = NULL;
}
if (commentp != NULL) {
*commentp = comment;
comment = NULL;
}
r = 0;
out:
sshkey_free(key);
free(comment);
return r;
}
#endif
static int
deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
{
int r;
char *comment = NULL;
const u_char *blob;
size_t blen;
if ((r = sshbuf_get_string_direct(ids, &blob, &blen)) != 0 ||
(r = sshbuf_get_cstring(ids, &comment, NULL)) != 0)
goto out;
if ((r = sshkey_from_blob(blob, blen, keyp)) != 0)
goto out;
if (commentp != NULL) {
*commentp = comment;
comment = NULL;
}
r = 0;
out:
free(comment);
return r;
}
/*
* Fetch list of identities held by the agent.
*/
int
ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
{
u_char type, code1 = 0, code2 = 0;
u_int32_t num, i;
struct sshbuf *msg;
struct ssh_identitylist *idl = NULL;
int r;
/* Determine request and expected response types */
switch (version) {
case 1:
code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
break;
case 2:
code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
break;
default:
return SSH_ERR_INVALID_ARGUMENT;
}
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, code1)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
/* Get message type, and verify that we got a proper answer. */
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
if (agent_failed(type)) {
r = SSH_ERR_AGENT_FAILURE;
goto out;
} else if (type != code2) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* Get the number of entries in the response and check it for sanity. */
if ((r = sshbuf_get_u32(msg, &num)) != 0)
goto out;
if (num > MAX_AGENT_IDENTITIES) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (num == 0) {
r = SSH_ERR_AGENT_NO_IDENTITIES;
goto out;
}
/* Deserialise the response into a list of keys/comments */
if ((idl = calloc(1, sizeof(*idl))) == NULL ||
(idl->keys = calloc(num, sizeof(*idl->keys))) == NULL ||
(idl->comments = calloc(num, sizeof(*idl->comments))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
for (i = 0; i < num;) {
switch (version) {
case 1:
#ifdef WITH_SSH1
if ((r = deserialise_identity1(msg,
&(idl->keys[i]), &(idl->comments[i]))) != 0)
goto out;
#endif
break;
case 2:
if ((r = deserialise_identity2(msg,
&(idl->keys[i]), &(idl->comments[i]))) != 0) {
if (r == SSH_ERR_KEY_TYPE_UNKNOWN) {
/* Gracefully skip unknown key types */
num--;
continue;
} else
goto out;
}
break;
}
i++;
}
idl->nkeys = num;
*idlp = idl;
idl = NULL;
r = 0;
out:
sshbuf_free(msg);
if (idl != NULL)
ssh_free_identitylist(idl);
return r;
}
void
ssh_free_identitylist(struct ssh_identitylist *idl)
{
size_t i;
if (idl == NULL)
return;
for (i = 0; i < idl->nkeys; i++) {
if (idl->keys != NULL)
sshkey_free(idl->keys[i]);
if (idl->comments != NULL)
free(idl->comments[i]);
}
free(idl);
}
/*
* Sends a challenge (typically from a server via ssh(1)) to the agent,
* and waits for a response from the agent.
* Returns true (non-zero) if the agent gave the correct answer, zero
* otherwise.
*/
#ifdef WITH_SSH1
int
ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
u_char session_id[16], u_char response[16])
{
struct sshbuf *msg;
int r;
u_char type;
if (key->type != KEY_RSA1)
return SSH_ERR_INVALID_ARGUMENT;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 ||
(r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 ||
(r = sshbuf_put_bignum1(msg, challenge)) != 0 ||
(r = sshbuf_put(msg, session_id, 16)) != 0 ||
(r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
if (agent_failed(type)) {
r = SSH_ERR_AGENT_FAILURE;
goto out;
} else if (type != SSH_AGENT_RSA_RESPONSE) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((r = sshbuf_get(msg, response, 16)) != 0)
goto out;
r = 0;
out:
sshbuf_free(msg);
return r;
}
#endif
/* ask agent to sign data, returns err.h code on error, 0 on success */
int
ssh_agent_sign(int sock, struct sshkey *key,
u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
struct sshbuf *msg;
u_char *blob = NULL, type;
size_t blen = 0, len = 0;
u_int flags = 0;
int r = SSH_ERR_INTERNAL_ERROR;
*sigp = NULL;
*lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
if (compat & SSH_BUG_SIGBLOB)
flags |= SSH_AGENT_OLD_SIGNATURE;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
goto out;
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_string(msg, data, datalen)) != 0 ||
(r = sshbuf_put_u32(msg, flags)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg) != 0))
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
if (agent_failed(type)) {
r = SSH_ERR_AGENT_FAILURE;
goto out;
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((r = sshbuf_get_string(msg, sigp, &len)) != 0)
goto out;
*lenp = len;
r = 0;
out:
if (blob != NULL) {
explicit_bzero(blob, blen);
free(blob);
}
sshbuf_free(msg);
return r;
}
/* Encode key for a message to the agent. */
#ifdef WITH_SSH1
static int
ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment)
{
int r;
/* To keep within the protocol: p < q for ssh. in SSL p > q */
if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 ||
(r = sshbuf_put_bignum1(b, key->n)) != 0 ||
(r = sshbuf_put_bignum1(b, key->e)) != 0 ||
(r = sshbuf_put_bignum1(b, key->d)) != 0 ||
(r = sshbuf_put_bignum1(b, key->iqmp)) != 0 ||
(r = sshbuf_put_bignum1(b, key->q)) != 0 ||
(r = sshbuf_put_bignum1(b, key->p)) != 0 ||
(r = sshbuf_put_cstring(b, comment)) != 0)
return r;
return 0;
}
#endif
static int
ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key,
const char *comment)
{
int r;
if ((r = sshkey_private_serialize(key, b)) != 0 ||
(r = sshbuf_put_cstring(b, comment)) != 0)
return r;
return 0;
}
static int
encode_constraints(struct sshbuf *m, u_int life, u_int confirm)
{
int r;
if (life != 0) {
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 ||
(r = sshbuf_put_u32(m, life)) != 0)
goto out;
}
if (confirm != 0) {
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0)
goto out;
}
r = 0;
out:
return r;
}
/*
* Adds an identity to the authentication server.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment,
u_int life, u_int confirm)
{
struct sshbuf *msg;
int r, constrained = (life || confirm);
u_char type;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
switch (key->type) {
#ifdef WITH_SSH1
case KEY_RSA1:
type = constrained ?
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
SSH_AGENTC_ADD_RSA_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0)
goto out;
break;
#endif
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_RSA_CERT:
case KEY_DSA:
case KEY_DSA_CERT:
case KEY_ECDSA:
case KEY_ECDSA_CERT:
#endif
case KEY_ED25519:
case KEY_ED25519_CERT:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = ssh_encode_identity_ssh2(msg, key, comment)) != 0)
goto out;
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if (constrained &&
(r = encode_constraints(msg, life, confirm)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
/*
* Removes an identity from the authentication server.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_remove_identity(int sock, struct sshkey *key)
{
struct sshbuf *msg;
int r;
u_char type, *blob = NULL;
size_t blen;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
#ifdef WITH_SSH1
if (key->type == KEY_RSA1) {
if ((r = sshbuf_put_u8(msg,
SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 ||
(r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0)
goto out;
} else
#endif
if (key->type != KEY_UNSPEC) {
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
goto out;
if ((r = sshbuf_put_u8(msg,
SSH2_AGENTC_REMOVE_IDENTITY)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0)
goto out;
} else {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
if (blob != NULL) {
explicit_bzero(blob, blen);
free(blob);
}
sshbuf_free(msg);
return r;
}
/*
* Add/remove an token-based identity from the authentication server.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
u_int life, u_int confirm)
{
struct sshbuf *msg;
int r, constrained = (life || confirm);
u_char type;
if (add) {
type = constrained ?
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED :
SSH_AGENTC_ADD_SMARTCARD_KEY;
} else
type = SSH_AGENTC_REMOVE_SMARTCARD_KEY;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshbuf_put_cstring(msg, reader_id)) != 0 ||
(r = sshbuf_put_cstring(msg, pin)) != 0)
goto out;
if (constrained &&
(r = encode_constraints(msg, life, confirm)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
/*
* Removes all identities from the agent.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_remove_all_identities(int sock, int version)
{
struct sshbuf *msg;
u_char type = (version == 1) ?
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
int r;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}

View File

@@ -0,0 +1,90 @@
/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions to interface with the SSH_AUTHENTICATION_FD socket.
*
* 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".
*/
#ifndef AUTHFD_H
#define AUTHFD_H
/* List of identities returned by ssh_fetch_identitylist() */
struct ssh_identitylist {
size_t nkeys;
struct sshkey **keys;
char **comments;
};
int ssh_get_authentication_socket(int *fdp);
void ssh_close_authentication_socket(int sock);
int ssh_lock_agent(int sock, int lock, const char *password);
int ssh_fetch_identitylist(int sock, int version,
struct ssh_identitylist **idlp);
void ssh_free_identitylist(struct ssh_identitylist *idl);
int ssh_add_identity_constrained(int sock, struct sshkey *key,
const char *comment, u_int life, u_int confirm);
int ssh_remove_identity(int sock, struct sshkey *key);
int ssh_update_card(int sock, int add, const char *reader_id,
const char *pin, u_int life, u_int confirm);
int ssh_remove_all_identities(int sock, int version);
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
u_char session_id[16], u_char response[16]);
int ssh_agent_sign(int sock, struct sshkey *key,
u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
/* Messages for the authentication agent connection. */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH_AGENTC_RSA_CHALLENGE 3
#define SSH_AGENT_RSA_RESPONSE 4
#define SSH_AGENT_FAILURE 5
#define SSH_AGENT_SUCCESS 6
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
/* private OpenSSH extensions for SSH2 */
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENT_SIGN_RESPONSE 14
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
/* smartcard */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
/* lock/unlock the agent */
#define SSH_AGENTC_LOCK 22
#define SSH_AGENTC_UNLOCK 23
/* add key with constraints */
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
/* additional error code for ssh.com's ssh-agent2 */
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
#endif /* AUTHFD_H */

View File

@@ -0,0 +1,580 @@
/* $OpenBSD: authfile.c,v 1.116 2015/07/09 09:49:46 markus Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "cipher.h"
#include "ssh.h"
#include "log.h"
#include "authfile.h"
#include "rsa.h"
#include "misc.h"
#include "atomicio.h"
#include "sshkey.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "krl.h"
#define MAX_KEY_FILE_SIZE (1024 * 1024)
/* Save a key blob to a file */
static int
sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
{
int fd, oerrno;
if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
return SSH_ERR_SYSTEM_ERROR;
if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
oerrno = errno;
close(fd);
unlink(filename);
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
close(fd);
return 0;
}
int
sshkey_save_private(struct sshkey *key, const char *filename,
const char *passphrase, const char *comment,
int force_new_format, const char *new_format_cipher, int new_format_rounds)
{
struct sshbuf *keyblob = NULL;
int r;
if ((keyblob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
force_new_format, new_format_cipher, new_format_rounds)) != 0)
goto out;
if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
goto out;
r = 0;
out:
sshbuf_free(keyblob);
return r;
}
/* Load a key from a fd into a buffer */
int
sshkey_load_file(int fd, struct sshbuf *blob)
{
u_char buf[1024];
size_t len;
struct stat st;
int r;
if (fstat(fd, &st) < 0)
return SSH_ERR_SYSTEM_ERROR;
if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
st.st_size > MAX_KEY_FILE_SIZE)
return SSH_ERR_INVALID_FORMAT;
for (;;) {
if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
if (errno == EPIPE)
break;
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
if ((r = sshbuf_put(blob, buf, len)) != 0)
goto out;
if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
}
if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
st.st_size != (off_t)sshbuf_len(blob)) {
r = SSH_ERR_FILE_CHANGED;
goto out;
}
r = 0;
out:
explicit_bzero(buf, sizeof(buf));
if (r != 0)
sshbuf_reset(blob);
return r;
}
#ifdef WITH_SSH1
/*
* Loads the public part of the ssh v1 key file. Returns NULL if an error was
* encountered (the file does not exist or is not readable), and the key
* otherwise.
*/
static int
sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp)
{
struct sshbuf *b = NULL;
int r;
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_load_file(fd, b)) != 0)
goto out;
if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
goto out;
r = 0;
out:
sshbuf_free(b);
return r;
}
#endif /* WITH_SSH1 */
/* XXX remove error() calls from here? */
int
sshkey_perm_ok(int fd, const char *filename)
{
struct stat st;
if (fstat(fd, &st) < 0)
return SSH_ERR_SYSTEM_ERROR;
/*
* if a key owned by the user is accessed, then we check the
* permissions of the file. if the key owned by a different user,
* then we don't care.
*/
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Permissions 0%3.3o for '%s' are too open.",
(u_int)st.st_mode & 0777, filename);
error("It is required that your private key files are NOT accessible by others.");
error("This private key will be ignored.");
return SSH_ERR_KEY_BAD_PERMISSIONS;
}
return 0;
}
/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
int
sshkey_load_private_type(int type, const char *filename, const char *passphrase,
struct sshkey **keyp, char **commentp, int *perm_ok)
{
int fd, r;
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
if ((fd = open(filename, O_RDONLY)) < 0) {
if (perm_ok != NULL)
*perm_ok = 0;
return SSH_ERR_SYSTEM_ERROR;
}
if (sshkey_perm_ok(fd, filename) != 0) {
if (perm_ok != NULL)
*perm_ok = 0;
r = SSH_ERR_KEY_BAD_PERMISSIONS;
goto out;
}
if (perm_ok != NULL)
*perm_ok = 1;
r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
out:
close(fd);
return r;
}
int
sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
struct sshkey **keyp, char **commentp)
{
struct sshbuf *buffer = NULL;
int r;
if ((buffer = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshkey_load_file(fd, buffer)) != 0 ||
(r = sshkey_parse_private_fileblob_type(buffer, type,
passphrase, keyp, commentp)) != 0)
goto out;
/* success */
r = 0;
out:
if (buffer != NULL)
sshbuf_free(buffer);
return r;
}
/* XXX this is almost identical to sshkey_load_private_type() */
int
sshkey_load_private(const char *filename, const char *passphrase,
struct sshkey **keyp, char **commentp)
{
struct sshbuf *buffer = NULL;
int r, fd;
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
if ((fd = open(filename, O_RDONLY)) < 0)
return SSH_ERR_SYSTEM_ERROR;
if (sshkey_perm_ok(fd, filename) != 0) {
r = SSH_ERR_KEY_BAD_PERMISSIONS;
goto out;
}
if ((buffer = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshkey_load_file(fd, buffer)) != 0 ||
(r = sshkey_parse_private_fileblob(buffer, passphrase, filename,
keyp, commentp)) != 0)
goto out;
r = 0;
out:
close(fd);
if (buffer != NULL)
sshbuf_free(buffer);
return r;
}
static int
sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
{
FILE *f;
char line[SSH_MAX_PUBKEY_BYTES];
char *cp;
u_long linenum = 0;
int r;
if (commentp != NULL)
*commentp = NULL;
if ((f = fopen(filename, "r")) == NULL)
return SSH_ERR_SYSTEM_ERROR;
while (read_keyfile_line(f, filename, line, sizeof(line),
&linenum) != -1) {
cp = line;
switch (*cp) {
case '#':
case '\n':
case '\0':
continue;
}
/* Abort loading if this looks like a private key */
if (strncmp(cp, "-----BEGIN", 10) == 0 ||
strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
break;
/* Skip leading whitespace. */
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
;
if (*cp) {
if ((r = sshkey_read(k, &cp)) == 0) {
cp[strcspn(cp, "\r\n")] = '\0';
if (commentp) {
*commentp = strdup(*cp ?
cp : filename);
if (*commentp == NULL)
r = SSH_ERR_ALLOC_FAIL;
}
fclose(f);
return r;
}
}
}
fclose(f);
return SSH_ERR_INVALID_FORMAT;
}
/* load public key from ssh v1 private or any pubkey file */
int
sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
{
struct sshkey *pub = NULL;
char file[PATH_MAX];
int r, fd;
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
/* XXX should load file once and attempt to parse each format */
if ((fd = open(filename, O_RDONLY)) < 0)
goto skip;
#ifdef WITH_SSH1
/* try rsa1 private key */
r = sshkey_load_public_rsa1(fd, keyp, commentp);
close(fd);
switch (r) {
case SSH_ERR_INTERNAL_ERROR:
case SSH_ERR_ALLOC_FAIL:
case SSH_ERR_INVALID_ARGUMENT:
case SSH_ERR_SYSTEM_ERROR:
case 0:
return r;
}
#else /* WITH_SSH1 */
close(fd);
#endif /* WITH_SSH1 */
/* try ssh2 public key */
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
if (keyp != NULL)
*keyp = pub;
return 0;
}
sshkey_free(pub);
#ifdef WITH_SSH1
/* try rsa1 public key */
if ((pub = sshkey_new(KEY_RSA1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
if (keyp != NULL)
*keyp = pub;
return 0;
}
sshkey_free(pub);
#endif /* WITH_SSH1 */
skip:
/* try .pub suffix */
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
return SSH_ERR_ALLOC_FAIL;
r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
(strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
(r = sshkey_try_load_public(pub, file, commentp)) == 0) {
if (keyp != NULL)
*keyp = pub;
return 0;
}
sshkey_free(pub);
return r;
}
/* Load the certificate associated with the named private key */
int
sshkey_load_cert(const char *filename, struct sshkey **keyp)
{
struct sshkey *pub = NULL;
char *file = NULL;
int r = SSH_ERR_INTERNAL_ERROR;
*keyp = NULL;
if (asprintf(&file, "%s-cert.pub", filename) == -1)
return SSH_ERR_ALLOC_FAIL;
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
goto out;
}
if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
goto out;
*keyp = pub;
pub = NULL;
r = 0;
out:
if (file != NULL)
free(file);
if (pub != NULL)
sshkey_free(pub);
return r;
}
/* Load private key and certificate */
int
sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
struct sshkey **keyp, int *perm_ok)
{
struct sshkey *key = NULL, *cert = NULL;
int r;
*keyp = NULL;
switch (type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_UNSPEC:
break;
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
if ((r = sshkey_load_private_type(type, filename,
passphrase, &key, NULL, perm_ok)) != 0 ||
(r = sshkey_load_cert(filename, &cert)) != 0)
goto out;
/* Make sure the private key matches the certificate */
if (sshkey_equal_public(key, cert) == 0) {
r = SSH_ERR_KEY_CERT_MISMATCH;
goto out;
}
if ((r = sshkey_to_certified(key)) != 0 ||
(r = sshkey_cert_copy(cert, key)) != 0)
goto out;
r = 0;
*keyp = key;
key = NULL;
out:
if (key != NULL)
sshkey_free(key);
if (cert != NULL)
sshkey_free(cert);
return r;
}
/*
* Returns success if the specified "key" is listed in the file "filename",
* SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
* If "strict_type" is set then the key type must match exactly,
* otherwise a comparison that ignores certficiate data is performed.
* If "check_ca" is set and "key" is a certificate, then its CA key is
* also checked and sshkey_in_file() will return success if either is found.
*/
int
sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
int check_ca)
{
FILE *f;
char line[SSH_MAX_PUBKEY_BYTES];
char *cp;
u_long linenum = 0;
int r = 0;
struct sshkey *pub = NULL;
int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
strict_type ? sshkey_equal : sshkey_equal_public;
if ((f = fopen(filename, "r")) == NULL)
return SSH_ERR_SYSTEM_ERROR;
while (read_keyfile_line(f, filename, line, sizeof(line),
&linenum) != -1) {
cp = line;
/* Skip leading whitespace. */
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
;
/* Skip comments and empty lines */
switch (*cp) {
case '#':
case '\n':
case '\0':
continue;
}
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshkey_read(pub, &cp)) != 0)
goto out;
if (sshkey_compare(key, pub) ||
(check_ca && sshkey_is_cert(key) &&
sshkey_compare(key->cert->signature_key, pub))) {
r = 0;
goto out;
}
sshkey_free(pub);
pub = NULL;
}
r = SSH_ERR_KEY_NOT_FOUND;
out:
if (pub != NULL)
sshkey_free(pub);
fclose(f);
return r;
}
/*
* Checks whether the specified key is revoked, returning 0 if not,
* SSH_ERR_KEY_REVOKED if it is or another error code if something
* unexpected happened.
* This will check both the key and, if it is a certificate, its CA key too.
* "revoked_keys_file" may be a KRL or a one-per-line list of public keys.
*/
int
sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
{
int r;
r = ssh_krl_file_contains_key(revoked_keys_file, key);
/* If this was not a KRL to begin with then continue below */
if (r != SSH_ERR_KRL_BAD_MAGIC)
return r;
/*
* If the file is not a KRL or we can't handle KRLs then attempt to
* parse the file as a flat list of keys.
*/
switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) {
case 0:
/* Key found => revoked */
return SSH_ERR_KEY_REVOKED;
case SSH_ERR_KEY_NOT_FOUND:
/* Key not found => not revoked */
return 0;
default:
/* Some other error occurred */
return r;
}
}

View File

@@ -0,0 +1,52 @@
/* $OpenBSD: authfile.h,v 1.21 2015/01/08 10:14:08 djm Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AUTHFILE_H
#define AUTHFILE_H
struct sshbuf;
struct sshkey;
/* XXX document these */
/* XXX some of these could probably be merged/retired */
int sshkey_save_private(struct sshkey *, const char *,
const char *, const char *, int, const char *, int);
int sshkey_load_file(int, struct sshbuf *);
int sshkey_load_cert(const char *, struct sshkey **);
int sshkey_load_public(const char *, struct sshkey **, char **);
int sshkey_load_private(const char *, const char *, struct sshkey **, char **);
int sshkey_load_private_cert(int, const char *, const char *,
struct sshkey **, int *);
int sshkey_load_private_type(int, const char *, const char *,
struct sshkey **, char **, int *);
int sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
struct sshkey **keyp, char **commentp);
int sshkey_perm_ok(int, const char *);
int sshkey_in_file(struct sshkey *, const char *, int, int);
int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file);
#endif

View File

@@ -0,0 +1 @@
openbsd-compat/bcrypt_pbkdf.c

View File

@@ -0,0 +1 @@
openbsd-compat/bindresvport.c

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2015 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include "bitmap.h"
#define BITMAP_WTYPE u_int
#define BITMAP_MAX (1<<24)
#define BITMAP_BYTES (sizeof(BITMAP_WTYPE))
#define BITMAP_BITS (sizeof(BITMAP_WTYPE) * 8)
#define BITMAP_WMASK ((BITMAP_WTYPE)BITMAP_BITS - 1)
struct bitmap {
BITMAP_WTYPE *d;
size_t len; /* number of words allocated */
size_t top; /* index of top word allocated */
};
struct bitmap *
bitmap_new(void)
{
struct bitmap *ret;
if ((ret = calloc(1, sizeof(*ret))) == NULL)
return NULL;
if ((ret->d = calloc(1, BITMAP_BYTES)) == NULL) {
free(ret);
return NULL;
}
ret->len = 1;
ret->top = 0;
return ret;
}
void
bitmap_free(struct bitmap *b)
{
if (b != NULL && b->d != NULL) {
memset(b->d, 0, b->len);
free(b->d);
}
free(b);
}
void
bitmap_zero(struct bitmap *b)
{
memset(b->d, 0, b->len * BITMAP_BYTES);
b->top = 0;
}
int
bitmap_test_bit(struct bitmap *b, u_int n)
{
if (b->top >= b->len)
return 0; /* invalid */
if (b->len == 0 || (n / BITMAP_BITS) > b->top)
return 0;
return (b->d[n / BITMAP_BITS] >> (n & BITMAP_WMASK)) & 1;
}
static int
reserve(struct bitmap *b, u_int n)
{
BITMAP_WTYPE *tmp;
size_t nlen;
if (b->top >= b->len || n > BITMAP_MAX)
return -1; /* invalid */
nlen = (n / BITMAP_BITS) + 1;
if (b->len < nlen) {
if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL)
return -1;
b->d = tmp;
memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES);
b->len = nlen;
}
return 0;
}
int
bitmap_set_bit(struct bitmap *b, u_int n)
{
int r;
size_t offset;
if ((r = reserve(b, n)) != 0)
return r;
offset = n / BITMAP_BITS;
if (offset > b->top)
b->top = offset;
b->d[offset] |= (BITMAP_WTYPE)1 << (n & BITMAP_WMASK);
return 0;
}
/* Resets b->top to point to the most significant bit set in b->d */
static void
retop(struct bitmap *b)
{
if (b->top >= b->len)
return;
while (b->top > 0 && b->d[b->top] == 0)
b->top--;
}
void
bitmap_clear_bit(struct bitmap *b, u_int n)
{
size_t offset;
if (b->top >= b->len || n > BITMAP_MAX)
return; /* invalid */
offset = n / BITMAP_BITS;
if (offset > b->top)
return;
b->d[offset] &= ~((BITMAP_WTYPE)1 << (n & BITMAP_WMASK));
/* The top may have changed as a result of the clear */
retop(b);
}
size_t
bitmap_nbits(struct bitmap *b)
{
size_t bits;
BITMAP_WTYPE w;
retop(b);
if (b->top >= b->len)
return 0; /* invalid */
if (b->len == 0 || (b->top == 0 && b->d[0] == 0))
return 0;
/* Find MSB set */
w = b->d[b->top];
bits = (b->top + 1) * BITMAP_BITS;
while (!(w & ((BITMAP_WTYPE)1 << (BITMAP_BITS - 1)))) {
w <<= 1;
bits--;
}
return bits;
}
size_t
bitmap_nbytes(struct bitmap *b)
{
return (bitmap_nbits(b) + 7) / 8;
}
int
bitmap_to_string(struct bitmap *b, void *p, size_t l)
{
u_char *s = (u_char *)p;
size_t i, j, k, need = bitmap_nbytes(b);
if (l < need || b->top >= b->len)
return -1;
if (l > need)
l = need;
/* Put the bytes from LSB backwards */
for (i = k = 0; i < b->top + 1; i++) {
for (j = 0; j < BITMAP_BYTES; j++) {
if (k >= l)
break;
s[need - 1 - k++] = (b->d[i] >> (j * 8)) & 0xff;
}
}
return 0;
}
int
bitmap_from_string(struct bitmap *b, const void *p, size_t l)
{
int r;
size_t i, offset, shift;
u_char *s = (u_char *)p;
if (l > BITMAP_MAX / 8)
return -1;
if ((r = reserve(b, l * 8)) != 0)
return r;
bitmap_zero(b);
if (l == 0)
return 0;
b->top = offset = ((l + (BITMAP_BYTES - 1)) / BITMAP_BYTES) - 1;
shift = ((l + (BITMAP_BYTES - 1)) % BITMAP_BYTES) * 8;
for (i = 0; i < l; i++) {
b->d[offset] |= (BITMAP_WTYPE)s[i] << shift;
if (shift == 0) {
offset--;
shift = BITMAP_BITS - 8;
} else
shift -= 8;
}
retop(b);
return 0;
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2015 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BITMAP_H
#define _BITMAP_H
#include <sys/types.h>
/* Simple bit vector routines */
struct bitmap;
/* Allocate a new bitmap. Returns NULL on allocation failure. */
struct bitmap *bitmap_new(void);
/* Free a bitmap */
void bitmap_free(struct bitmap *b);
/* Zero an existing bitmap */
void bitmap_zero(struct bitmap *b);
/* Test whether a bit is set in a bitmap. */
int bitmap_test_bit(struct bitmap *b, u_int n);
/* Set a bit in a bitmap. Returns 0 on success or -1 on error */
int bitmap_set_bit(struct bitmap *b, u_int n);
/* Clear a bit in a bitmap */
void bitmap_clear_bit(struct bitmap *b, u_int n);
/* Return the number of bits in a bitmap (i.e. the position of the MSB) */
size_t bitmap_nbits(struct bitmap *b);
/* Return the number of bytes needed to represent a bitmap */
size_t bitmap_nbytes(struct bitmap *b);
/* Convert a bitmap to a big endian byte string */
int bitmap_to_string(struct bitmap *b, void *p, size_t l);
/* Convert a big endian byte string to a bitmap */
int bitmap_from_string(struct bitmap *b, const void *p, size_t l);
#endif /* _BITMAP_H */

88
crypto/external/bsd/openssh/dist/blf.h vendored Normal file
View File

@@ -0,0 +1,88 @@
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
/*
* Blowfish - a fast block cipher designed by Bruce Schneier
*
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Niels Provos.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BLF_H_
#define _BLF_H_
#include "includes.h"
#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
/* Schneier specifies a maximum key length of 56 bytes.
* This ensures that every key bit affects every cipher
* bit. However, the subkeys can hold up to 72 bytes.
* Warning: For normal blowfish encryption only 56 bytes
* of the key affect all cipherbits.
*/
#define BLF_N 16 /* Number of Subkeys */
#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */
/* Blowfish context */
typedef struct BlowfishContext {
u_int32_t S[4][256]; /* S-Boxes */
u_int32_t P[BLF_N + 2]; /* Subkeys */
} blf_ctx;
/* Raw access to customized Blowfish
* blf_key is just:
* Blowfish_initstate( state )
* Blowfish_expand0state( state, key, keylen )
*/
void Blowfish_encipher(blf_ctx *, u_int32_t *, u_int32_t *);
void Blowfish_decipher(blf_ctx *, u_int32_t *, u_int32_t *);
void Blowfish_initstate(blf_ctx *);
void Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t);
void Blowfish_expandstate
(blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t);
/* Standard Blowfish */
void blf_key(blf_ctx *, const u_int8_t *, u_int16_t);
void blf_enc(blf_ctx *, u_int32_t *, u_int16_t);
void blf_dec(blf_ctx *, u_int32_t *, u_int16_t);
void blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t);
void blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t);
void blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);
void blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);
/* Converts u_int8_t to u_int32_t */
u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t , u_int16_t *);
#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
#endif /* _BLF_H */

View File

@@ -0,0 +1,248 @@
/* $OpenBSD: blocks.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
/*
* Public Domain, Author: Daniel J. Bernstein
* Copied from nacl-20110221/crypto_hashblocks/sha512/ref/blocks.c
*/
#include "includes.h"
__RCSID("$NetBSD: blocks.c,v 1.3 2015/04/03 23:58:19 christos Exp $");
#include "crypto_api.h"
typedef unsigned long long uint64;
static uint64 load_bigendian(const unsigned char *x)
{
return
(uint64) (x[7]) \
| (((uint64) (x[6])) << 8) \
| (((uint64) (x[5])) << 16) \
| (((uint64) (x[4])) << 24) \
| (((uint64) (x[3])) << 32) \
| (((uint64) (x[2])) << 40) \
| (((uint64) (x[1])) << 48) \
| (((uint64) (x[0])) << 56)
;
}
static void store_bigendian(unsigned char *x,uint64 u)
{
x[7] = u; u >>= 8;
x[6] = u; u >>= 8;
x[5] = u; u >>= 8;
x[4] = u; u >>= 8;
x[3] = u; u >>= 8;
x[2] = u; u >>= 8;
x[1] = u; u >>= 8;
x[0] = u;
}
#define SHR(x,c) ((x) >> (c))
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
#define Ch(x,y,z) ((x & y) ^ (~x & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
#define EXPAND \
M(w0 ,w14,w9 ,w1 ) \
M(w1 ,w15,w10,w2 ) \
M(w2 ,w0 ,w11,w3 ) \
M(w3 ,w1 ,w12,w4 ) \
M(w4 ,w2 ,w13,w5 ) \
M(w5 ,w3 ,w14,w6 ) \
M(w6 ,w4 ,w15,w7 ) \
M(w7 ,w5 ,w0 ,w8 ) \
M(w8 ,w6 ,w1 ,w9 ) \
M(w9 ,w7 ,w2 ,w10) \
M(w10,w8 ,w3 ,w11) \
M(w11,w9 ,w4 ,w12) \
M(w12,w10,w5 ,w13) \
M(w13,w11,w6 ,w14) \
M(w14,w12,w7 ,w15) \
M(w15,w13,w8 ,w0 )
#define F(w,k) \
T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
T2 = Sigma0(a) + Maj(a,b,c); \
h = g; \
g = f; \
f = e; \
e = d + T1; \
d = c; \
c = b; \
b = a; \
a = T1 + T2;
int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
{
uint64 state[8];
uint64 a;
uint64 b;
uint64 c;
uint64 d;
uint64 e;
uint64 f;
uint64 g;
uint64 h;
uint64 T1;
uint64 T2;
a = load_bigendian(statebytes + 0); state[0] = a;
b = load_bigendian(statebytes + 8); state[1] = b;
c = load_bigendian(statebytes + 16); state[2] = c;
d = load_bigendian(statebytes + 24); state[3] = d;
e = load_bigendian(statebytes + 32); state[4] = e;
f = load_bigendian(statebytes + 40); state[5] = f;
g = load_bigendian(statebytes + 48); state[6] = g;
h = load_bigendian(statebytes + 56); state[7] = h;
while (inlen >= 128) {
uint64 w0 = load_bigendian(in + 0);
uint64 w1 = load_bigendian(in + 8);
uint64 w2 = load_bigendian(in + 16);
uint64 w3 = load_bigendian(in + 24);
uint64 w4 = load_bigendian(in + 32);
uint64 w5 = load_bigendian(in + 40);
uint64 w6 = load_bigendian(in + 48);
uint64 w7 = load_bigendian(in + 56);
uint64 w8 = load_bigendian(in + 64);
uint64 w9 = load_bigendian(in + 72);
uint64 w10 = load_bigendian(in + 80);
uint64 w11 = load_bigendian(in + 88);
uint64 w12 = load_bigendian(in + 96);
uint64 w13 = load_bigendian(in + 104);
uint64 w14 = load_bigendian(in + 112);
uint64 w15 = load_bigendian(in + 120);
F(w0 ,0x428a2f98d728ae22ULL)
F(w1 ,0x7137449123ef65cdULL)
F(w2 ,0xb5c0fbcfec4d3b2fULL)
F(w3 ,0xe9b5dba58189dbbcULL)
F(w4 ,0x3956c25bf348b538ULL)
F(w5 ,0x59f111f1b605d019ULL)
F(w6 ,0x923f82a4af194f9bULL)
F(w7 ,0xab1c5ed5da6d8118ULL)
F(w8 ,0xd807aa98a3030242ULL)
F(w9 ,0x12835b0145706fbeULL)
F(w10,0x243185be4ee4b28cULL)
F(w11,0x550c7dc3d5ffb4e2ULL)
F(w12,0x72be5d74f27b896fULL)
F(w13,0x80deb1fe3b1696b1ULL)
F(w14,0x9bdc06a725c71235ULL)
F(w15,0xc19bf174cf692694ULL)
EXPAND
F(w0 ,0xe49b69c19ef14ad2ULL)
F(w1 ,0xefbe4786384f25e3ULL)
F(w2 ,0x0fc19dc68b8cd5b5ULL)
F(w3 ,0x240ca1cc77ac9c65ULL)
F(w4 ,0x2de92c6f592b0275ULL)
F(w5 ,0x4a7484aa6ea6e483ULL)
F(w6 ,0x5cb0a9dcbd41fbd4ULL)
F(w7 ,0x76f988da831153b5ULL)
F(w8 ,0x983e5152ee66dfabULL)
F(w9 ,0xa831c66d2db43210ULL)
F(w10,0xb00327c898fb213fULL)
F(w11,0xbf597fc7beef0ee4ULL)
F(w12,0xc6e00bf33da88fc2ULL)
F(w13,0xd5a79147930aa725ULL)
F(w14,0x06ca6351e003826fULL)
F(w15,0x142929670a0e6e70ULL)
EXPAND
F(w0 ,0x27b70a8546d22ffcULL)
F(w1 ,0x2e1b21385c26c926ULL)
F(w2 ,0x4d2c6dfc5ac42aedULL)
F(w3 ,0x53380d139d95b3dfULL)
F(w4 ,0x650a73548baf63deULL)
F(w5 ,0x766a0abb3c77b2a8ULL)
F(w6 ,0x81c2c92e47edaee6ULL)
F(w7 ,0x92722c851482353bULL)
F(w8 ,0xa2bfe8a14cf10364ULL)
F(w9 ,0xa81a664bbc423001ULL)
F(w10,0xc24b8b70d0f89791ULL)
F(w11,0xc76c51a30654be30ULL)
F(w12,0xd192e819d6ef5218ULL)
F(w13,0xd69906245565a910ULL)
F(w14,0xf40e35855771202aULL)
F(w15,0x106aa07032bbd1b8ULL)
EXPAND
F(w0 ,0x19a4c116b8d2d0c8ULL)
F(w1 ,0x1e376c085141ab53ULL)
F(w2 ,0x2748774cdf8eeb99ULL)
F(w3 ,0x34b0bcb5e19b48a8ULL)
F(w4 ,0x391c0cb3c5c95a63ULL)
F(w5 ,0x4ed8aa4ae3418acbULL)
F(w6 ,0x5b9cca4f7763e373ULL)
F(w7 ,0x682e6ff3d6b2b8a3ULL)
F(w8 ,0x748f82ee5defb2fcULL)
F(w9 ,0x78a5636f43172f60ULL)
F(w10,0x84c87814a1f0ab72ULL)
F(w11,0x8cc702081a6439ecULL)
F(w12,0x90befffa23631e28ULL)
F(w13,0xa4506cebde82bde9ULL)
F(w14,0xbef9a3f7b2c67915ULL)
F(w15,0xc67178f2e372532bULL)
EXPAND
F(w0 ,0xca273eceea26619cULL)
F(w1 ,0xd186b8c721c0c207ULL)
F(w2 ,0xeada7dd6cde0eb1eULL)
F(w3 ,0xf57d4f7fee6ed178ULL)
F(w4 ,0x06f067aa72176fbaULL)
F(w5 ,0x0a637dc5a2c898a6ULL)
F(w6 ,0x113f9804bef90daeULL)
F(w7 ,0x1b710b35131c471bULL)
F(w8 ,0x28db77f523047d84ULL)
F(w9 ,0x32caab7b40c72493ULL)
F(w10,0x3c9ebe0a15c9bebcULL)
F(w11,0x431d67c49c100d4cULL)
F(w12,0x4cc5d4becb3e42b6ULL)
F(w13,0x597f299cfc657e2aULL)
F(w14,0x5fcb6fab3ad6faecULL)
F(w15,0x6c44198c4a475817ULL)
a += state[0];
b += state[1];
c += state[2];
d += state[3];
e += state[4];
f += state[5];
g += state[6];
h += state[7];
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
state[4] = e;
state[5] = f;
state[6] = g;
state[7] = h;
in += 128;
inlen -= 128;
}
store_bigendian(statebytes + 0,state[0]);
store_bigendian(statebytes + 8,state[1]);
store_bigendian(statebytes + 16,state[2]);
store_bigendian(statebytes + 24,state[3]);
store_bigendian(statebytes + 32,state[4]);
store_bigendian(statebytes + 40,state[5]);
store_bigendian(statebytes + 48,state[6]);
store_bigendian(statebytes + 56,state[7]);
return inlen;
}

View File

@@ -0,0 +1 @@
openbsd-compat/blowfish.c

View File

@@ -0,0 +1 @@
openbsd-compat/bsd-misc.c

View File

@@ -0,0 +1 @@
openbsd-compat/bsd-setres_id.c

View File

@@ -0,0 +1,259 @@
/* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */
/*
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#include <sys/types.h>
#include "buffer.h"
#include "log.h"
#include "ssherr.h"
int
buffer_get_short_ret(u_short *v, Buffer *buffer)
{
int ret;
if ((ret = sshbuf_get_u16(buffer, v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
u_short
buffer_get_short(Buffer *buffer)
{
u_short ret;
if (buffer_get_short_ret(&ret, buffer) == -1)
fatal("%s: buffer error", __func__);
return (ret);
}
int
buffer_get_int_ret(u_int *v, Buffer *buffer)
{
int ret;
if ((ret = sshbuf_get_u32(buffer, v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
u_int
buffer_get_int(Buffer *buffer)
{
u_int ret;
if (buffer_get_int_ret(&ret, buffer) == -1)
fatal("%s: buffer error", __func__);
return (ret);
}
int
buffer_get_int64_ret(u_int64_t *v, Buffer *buffer)
{
int ret;
if ((ret = sshbuf_get_u64(buffer, v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
u_int64_t
buffer_get_int64(Buffer *buffer)
{
u_int64_t ret;
if (buffer_get_int64_ret(&ret, buffer) == -1)
fatal("%s: buffer error", __func__);
return (ret);
}
void
buffer_put_short(Buffer *buffer, u_short value)
{
int ret;
if ((ret = sshbuf_put_u16(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_int(Buffer *buffer, u_int value)
{
int ret;
if ((ret = sshbuf_put_u32(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_int64(Buffer *buffer, u_int64_t value)
{
int ret;
if ((ret = sshbuf_put_u64(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void *
buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
{
size_t len;
int ret;
u_char *value;
if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return NULL;
}
if (length_ptr != NULL)
*length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
return value;
}
void *
buffer_get_string(Buffer *buffer, u_int *length_ptr)
{
void *ret;
if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
fatal("%s: buffer error", __func__);
return (ret);
}
char *
buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
{
size_t len;
int ret;
char *value;
if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return NULL;
}
if (length_ptr != NULL)
*length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
return value;
}
char *
buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
{
char *ret;
if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
fatal("%s: buffer error", __func__);
return ret;
}
const void *
buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
{
size_t len;
int ret;
const u_char *value;
if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return NULL;
}
if (length_ptr != NULL)
*length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
return value;
}
const void *
buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
{
const void *ret;
if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
fatal("%s: buffer error", __func__);
return (ret);
}
void
buffer_put_string(Buffer *buffer, const void *buf, u_int len)
{
int ret;
if ((ret = sshbuf_put_string(buffer, buf, len)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
int ret;
if ((ret = sshbuf_put_cstring(buffer, s)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
int
buffer_get_char_ret(char *v, Buffer *buffer)
{
int ret;
if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
int
buffer_get_char(Buffer *buffer)
{
char ch;
if (buffer_get_char_ret(&ch, buffer) == -1)
fatal("%s: buffer error", __func__);
return (u_char) ch;
}
void
buffer_put_char(Buffer *buffer, int value)
{
int ret;
if ((ret = sshbuf_put_u8(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
{
int ret;
if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}

109
crypto/external/bsd/openssh/dist/bufbn.c vendored Normal file
View File

@@ -0,0 +1,109 @@
/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */
/*
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include "buffer.h"
#include "log.h"
#include "ssherr.h"
#ifdef WITH_SSH1
int
buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
{
int ret;
if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
{
if (buffer_put_bignum_ret(buffer, value) == -1)
fatal("%s: buffer error", __func__);
}
int
buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
{
int ret;
if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
{
if (buffer_get_bignum_ret(buffer, value) == -1)
fatal("%s: buffer error", __func__);
}
#endif /* WITH_SSH1 */
int
buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
{
int ret;
if ((ret = sshbuf_put_bignum2(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
{
if (buffer_put_bignum2_ret(buffer, value) == -1)
fatal("%s: buffer error", __func__);
}
int
buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
{
int ret;
if ((ret = sshbuf_get_bignum2(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
{
if (buffer_get_bignum2_ret(buffer, value) == -1)
fatal("%s: buffer error", __func__);
}
#endif /* WITH_OPENSSL */

View File

@@ -0,0 +1,74 @@
/* $OpenBSD: bufec.c,v 1.4 2014/04/30 05:29:56 djm Exp $ */
/*
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#include <sys/types.h>
#include "buffer.h"
#include "log.h"
#include "ssherr.h"
#ifdef OPENSSL_HAS_ECC
int
buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
const EC_POINT *point)
{
int ret;
if ((ret = sshbuf_put_ec(buffer, point, curve)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve,
const EC_POINT *point)
{
if (buffer_put_ecpoint_ret(buffer, curve, point) == -1)
fatal("%s: buffer error", __func__);
}
int
buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
EC_POINT *point)
{
int ret;
if ((ret = sshbuf_get_ec(buffer, point, curve)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
EC_POINT *point)
{
if (buffer_get_ecpoint_ret(buffer, curve, point) == -1)
fatal("%s: buffer error", __func__);
}
#endif /* OPENSSL_HAS_ECC */

View File

@@ -0,0 +1,118 @@
/* $OpenBSD: buffer.c,v 1.36 2014/04/30 05:29:56 djm Exp $ */
/*
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#include <sys/types.h>
#include "buffer.h"
#include "log.h"
#include "ssherr.h"
void
buffer_append(Buffer *buffer, const void *data, u_int len)
{
int ret;
if ((ret = sshbuf_put(buffer, data, len)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void *
buffer_append_space(Buffer *buffer, u_int len)
{
int ret;
u_char *p;
if ((ret = sshbuf_reserve(buffer, len, &p)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
return p;
}
int
buffer_check_alloc(Buffer *buffer, u_int len)
{
int ret = sshbuf_check_reserve(buffer, len);
if (ret == 0)
return 1;
if (ret == SSH_ERR_NO_BUFFER_SPACE)
return 0;
fatal("%s: %s", __func__, ssh_err(ret));
}
int
buffer_get_ret(Buffer *buffer, void *buf, u_int len)
{
int ret;
if ((ret = sshbuf_get(buffer, buf, len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
void
buffer_get(Buffer *buffer, void *buf, u_int len)
{
if (buffer_get_ret(buffer, buf, len) == -1)
fatal("%s: buffer error", __func__);
}
int
buffer_consume_ret(Buffer *buffer, u_int bytes)
{
int ret = sshbuf_consume(buffer, bytes);
if (ret == 0)
return 0;
if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
return -1;
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_consume(Buffer *buffer, u_int bytes)
{
if (buffer_consume_ret(buffer, bytes) == -1)
fatal("%s: buffer error", __func__);
}
int
buffer_consume_end_ret(Buffer *buffer, u_int bytes)
{
int ret = sshbuf_consume_end(buffer, bytes);
if (ret == 0)
return 0;
if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
return -1;
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_consume_end(Buffer *buffer, u_int bytes)
{
if (buffer_consume_end_ret(buffer, bytes) == -1)
fatal("%s: buffer error", __func__);
}

View File

@@ -0,0 +1,99 @@
/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */
/*
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#ifndef BUFFER_H
#define BUFFER_H
#include "sshbuf.h"
typedef struct sshbuf Buffer;
#define buffer_init(b) sshbuf_init(b)
#define buffer_clear(b) sshbuf_reset(b)
#define buffer_free(b) sshbuf_free(b)
#define buffer_dump(b) sshbuf_dump(b, stderr)
/* XXX cast is safe: sshbuf never stores more than len 2^31 */
#define buffer_len(b) ((u_int) sshbuf_len(b))
#define buffer_ptr(b) sshbuf_mutable_ptr(b)
void buffer_append(Buffer *, const void *, u_int);
void *buffer_append_space(Buffer *, u_int);
int buffer_check_alloc(Buffer *, u_int);
void buffer_get(Buffer *, void *, u_int);
void buffer_consume(Buffer *, u_int);
void buffer_consume_end(Buffer *, u_int);
int buffer_get_ret(Buffer *, void *, u_int);
int buffer_consume_ret(Buffer *, u_int);
int buffer_consume_end_ret(Buffer *, u_int);
#include <openssl/objects.h>
#include <openssl/bn.h>
void buffer_put_bignum(Buffer *, const BIGNUM *);
void buffer_put_bignum2(Buffer *, const BIGNUM *);
void buffer_get_bignum(Buffer *, BIGNUM *);
void buffer_get_bignum2(Buffer *, BIGNUM *);
void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int);
u_short buffer_get_short(Buffer *);
void buffer_put_short(Buffer *, u_short);
u_int buffer_get_int(Buffer *);
void buffer_put_int(Buffer *, u_int);
u_int64_t buffer_get_int64(Buffer *);
void buffer_put_int64(Buffer *, u_int64_t);
int buffer_get_char(Buffer *);
void buffer_put_char(Buffer *, int);
void *buffer_get_string(Buffer *, u_int *);
const void *buffer_get_string_ptr(Buffer *, u_int *);
void buffer_put_string(Buffer *, const void *, u_int);
char *buffer_get_cstring(Buffer *, u_int *);
void buffer_put_cstring(Buffer *, const char *);
#define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL);
int buffer_put_bignum_ret(Buffer *, const BIGNUM *);
int buffer_get_bignum_ret(Buffer *, BIGNUM *);
int buffer_put_bignum2_ret(Buffer *, const BIGNUM *);
int buffer_get_bignum2_ret(Buffer *, BIGNUM *);
int buffer_get_short_ret(u_short *, Buffer *);
int buffer_get_int_ret(u_int *, Buffer *);
int buffer_get_int64_ret(u_int64_t *, Buffer *);
void *buffer_get_string_ret(Buffer *, u_int *);
char *buffer_get_cstring_ret(Buffer *, u_int *);
const void *buffer_get_string_ptr_ret(Buffer *, u_int *);
int buffer_get_char_ret(char *, Buffer *);
#ifdef OPENSSL_HAS_ECC
#include <openssl/ec.h>
int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *);
void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *);
int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *);
void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *);
#endif
#endif /* BUFFER_H */

View File

@@ -0,0 +1,446 @@
/* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for returning the canonical host name of the remote site.
*
* 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".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "xmalloc.h"
#include "packet.h"
#include "log.h"
#include "canohost.h"
#include "misc.h"
static void check_ip_options(int, char *);
static char *canonical_host_ip = NULL;
static int cached_port = -1;
/*
* Return the canonical name of the host at the other end of the socket. The
* caller should free the returned string.
*/
static char *
get_remote_hostname(int sock, int use_dns)
{
struct sockaddr_storage from;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
cleanup_exit(255);
}
if (from.ss_family == AF_INET)
check_ip_options(sock, ntop);
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
if (!use_dns)
return xstrdup(ntop);
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) != 0) {
/* Host name not found. Use ip address. */
return xstrdup(ntop);
}
/*
* if reverse lookup result looks like a numeric hostname,
* someone is trying to trick us by PTR record like following:
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
*/
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
name, ntop);
freeaddrinfo(ai);
return xstrdup(ntop);
}
/* Names are stores in lowercase. */
lowercase(name);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
logit("reverse mapping checking getaddrinfo for %.700s "
"[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
return xstrdup(ntop);
}
/* Look for the address from the list of addresses. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
(strcmp(ntop, ntop2) == 0))
break;
}
freeaddrinfo(aitop);
/* If we reached the end of the list, the address was not there. */
if (!ai) {
/* Address not found for the host name. */
logit("Address %.100s maps to %.600s, but this does not "
"map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
ntop, name);
return xstrdup(ntop);
}
return xstrdup(name);
}
/*
* If IP options are supported, make sure there are none (log and
* disconnect them if any are found). Basically we are worried about
* source routing; it can be used to pretend you are somebody
* (ip-address) you are not. That itself may be "almost acceptable"
* under certain circumstances, but rhosts autentication is useless
* if source routing is accepted. Notice also that if we just dropped
* source routing here, the other side could use IP spoofing to do
* rest of the interaction and could still bypass security. So we
* exit here if we detect any IP options.
*/
/* IPv4 only */
static void
check_ip_options(int sock, char *ipaddr)
{
#ifdef IP_OPTIONS
u_char options[200];
char text[sizeof(options) * 3 + 1];
socklen_t option_size, i;
int ipproto;
struct protoent *ip;
if ((ip = getprotobyname("ip")) != NULL)
ipproto = ip->p_proto;
else
ipproto = IPPROTO_IP;
option_size = sizeof(options);
if (getsockopt(sock, ipproto, IP_OPTIONS, options,
&option_size) >= 0 && option_size != 0) {
text[0] = '\0';
for (i = 0; i < option_size; i++)
snprintf(text + i*3, sizeof(text) - i*3,
" %2.2x", options[i]);
fatal("Connection from %.100s with IP options:%.800s",
ipaddr, text);
}
#endif /* IP_OPTIONS */
}
void
ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
{
struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr;
struct sockaddr_in *a4 = (struct sockaddr_in *)addr;
struct in_addr inaddr;
u_int16_t port;
if (addr->ss_family != AF_INET6 ||
!IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr))
return;
debug3("Normalising mapped IPv4 in IPv6 address");
memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
port = a6->sin6_port;
memset(a4, 0, sizeof(*a4));
a4->sin_family = AF_INET;
*len = sizeof(*a4);
memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr));
a4->sin_port = port;
}
/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
* several times.
*/
const char *
get_canonical_hostname(int use_dns)
{
char *host;
static char *canonical_host_name = NULL;
static char *remote_ip = NULL;
/* Check if we have previously retrieved name with same option. */
if (use_dns && canonical_host_name != NULL)
return canonical_host_name;
if (!use_dns && remote_ip != NULL)
return remote_ip;
/* Get the real hostname if socket; otherwise return UNKNOWN. */
if (packet_connection_is_on_socket())
host = get_remote_hostname(packet_get_connection_in(), use_dns);
else
host = "UNKNOWN";
if (use_dns)
canonical_host_name = host;
else
remote_ip = host;
return host;
}
/*
* Returns the local/remote IP-address/hostname of socket as a string.
* The returned string must be freed.
*/
static char *
get_socket_address(int sock, int remote, int flags)
{
struct sockaddr_storage addr;
socklen_t addrlen;
char ntop[NI_MAXHOST];
int r;
/* Get IP address of client. */
addrlen = sizeof(addr);
memset(&addr, 0, sizeof(addr));
if (remote) {
if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
< 0)
return NULL;
} else {
if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
< 0)
return NULL;
}
/* Work around Linux IPv6 weirdness */
if (addr.ss_family == AF_INET6) {
addrlen = sizeof(struct sockaddr_in6);
ipv64_normalise_mapped(&addr, &addrlen);
}
switch (addr.ss_family) {
case AF_INET:
case AF_INET6:
/* Get the address in ascii. */
if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
sizeof(ntop), NULL, 0, flags)) != 0) {
error("get_socket_address: getnameinfo %d failed: %s",
flags, ssh_gai_strerror(r));
return NULL;
}
return xstrdup(ntop);
case AF_UNIX:
/* Get the Unix domain socket path. */
return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
default:
/* We can't look up remote Unix domain sockets. */
return NULL;
}
}
char *
get_peer_ipaddr(int sock)
{
char *p;
if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL)
return p;
return xstrdup("UNKNOWN");
}
char *
get_local_ipaddr(int sock)
{
char *p;
if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL)
return p;
return xstrdup("UNKNOWN");
}
char *
get_local_name(int fd)
{
char *host, myname[NI_MAXHOST];
/* Assume we were passed a socket */
if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL)
return host;
/* Handle the case where we were passed a pipe */
if (gethostname(myname, sizeof(myname)) == -1) {
verbose("get_local_name: gethostname: %s", strerror(errno));
} else {
host = xstrdup(myname);
}
return host;
}
void
clear_cached_addr(void)
{
free(canonical_host_ip);
canonical_host_ip = NULL;
cached_port = -1;
}
/*
* Returns the IP-address of the remote host as a string. The returned
* string must not be freed.
*/
const char *
get_remote_ipaddr(void)
{
/* Check whether we have cached the ipaddr. */
if (canonical_host_ip == NULL) {
if (packet_connection_is_on_socket()) {
canonical_host_ip =
get_peer_ipaddr(packet_get_connection_in());
if (canonical_host_ip == NULL)
cleanup_exit(255);
} else {
/* If not on socket, return UNKNOWN. */
canonical_host_ip = xstrdup("UNKNOWN");
}
}
return canonical_host_ip;
}
const char *
get_remote_name_or_ip(u_int utmp_len, int use_dns)
{
static const char *remote = "";
if (utmp_len > 0)
remote = get_canonical_hostname(use_dns);
if (utmp_len == 0 || strlen(remote) > utmp_len)
remote = get_remote_ipaddr();
return remote;
}
/* Returns the local/remote port for the socket. */
int
get_sock_port(int sock, int local)
{
struct sockaddr_storage from;
socklen_t fromlen;
char strport[NI_MAXSERV];
int r;
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (local) {
if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
error("getsockname failed: %.100s", strerror(errno));
return 0;
}
} else {
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
return -1;
}
}
/* Work around Linux IPv6 weirdness */
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
/* Non-inet sockets don't have a port number. */
if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
return 0;
/* Return port number. */
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV)) != 0)
fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed: %s",
ssh_gai_strerror(r));
return atoi(strport);
}
/* Returns remote/local port number for the current connection. */
static int
get_port(int local)
{
/*
* If the connection is not a socket, return 65535. This is
* intentionally chosen to be an unprivileged port number.
*/
if (!packet_connection_is_on_socket())
return 65535;
/* Get socket and return the port number. */
return get_sock_port(packet_get_connection_in(), local);
}
int
get_peer_port(int sock)
{
return get_sock_port(sock, 0);
}
int
get_remote_port(void)
{
/* Cache to avoid getpeername() on a dead connection */
if (cached_port == -1)
cached_port = get_port(0);
return cached_port;
}
int
get_local_port(void)
{
return get_port(1);
}

View File

@@ -0,0 +1,29 @@
/* $OpenBSD: canohost.h,v 1.11 2009/05/27 06:31:25 andreas Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* 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".
*/
const char *get_canonical_hostname(int);
const char *get_remote_ipaddr(void);
const char *get_remote_name_or_ip(u_int, int);
char *get_peer_ipaddr(int);
int get_peer_port(int);
char *get_local_ipaddr(int);
char *get_local_name(int);
int get_remote_port(void);
int get_local_port(void);
int get_sock_port(int, int);
void clear_cached_addr(void);
void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);

View File

@@ -0,0 +1,219 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#include "includes.h"
#include "chacha.h"
/* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct chacha_ctx chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((u8)(v) & U8C(0xFF))
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((u32)((p)[0]) ) | \
((u32)((p)[1]) << 8) | \
((u32)((p)[2]) << 16) | \
((u32)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
void
chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
{
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
void
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
u8 *ctarget = NULL;
u8 tmp[64];
u_int i;
if (!bytes) return;
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) tmp[i] = m[i];
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20;i > 0;i -= 2) {
QUARTERROUND( x0, x4, x8,x12)
QUARTERROUND( x1, x5, x9,x13)
QUARTERROUND( x2, x6,x10,x14)
QUARTERROUND( x3, x7,x11,x15)
QUARTERROUND( x0, x5,x10,x15)
QUARTERROUND( x1, x6,x11,x12)
QUARTERROUND( x2, x7, x8,x13)
QUARTERROUND( x3, x4, x9,x14)
}
x0 = PLUS(x0,j0);
x1 = PLUS(x1,j1);
x2 = PLUS(x2,j2);
x3 = PLUS(x3,j3);
x4 = PLUS(x4,j4);
x5 = PLUS(x5,j5);
x6 = PLUS(x6,j6);
x7 = PLUS(x7,j7);
x8 = PLUS(x8,j8);
x9 = PLUS(x9,j9);
x10 = PLUS(x10,j10);
x11 = PLUS(x11,j11);
x12 = PLUS(x12,j12);
x13 = PLUS(x13,j13);
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
x3 = XOR(x3,U8TO32_LITTLE(m + 12));
x4 = XOR(x4,U8TO32_LITTLE(m + 16));
x5 = XOR(x5,U8TO32_LITTLE(m + 20));
x6 = XOR(x6,U8TO32_LITTLE(m + 24));
x7 = XOR(x7,U8TO32_LITTLE(m + 28));
x8 = XOR(x8,U8TO32_LITTLE(m + 32));
x9 = XOR(x9,U8TO32_LITTLE(m + 36));
x10 = XOR(x10,U8TO32_LITTLE(m + 40));
x11 = XOR(x11,U8TO32_LITTLE(m + 44));
x12 = XOR(x12,U8TO32_LITTLE(m + 48));
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
j12 = PLUSONE(j12);
if (!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0,x0);
U32TO8_LITTLE(c + 4,x1);
U32TO8_LITTLE(c + 8,x2);
U32TO8_LITTLE(c + 12,x3);
U32TO8_LITTLE(c + 16,x4);
U32TO8_LITTLE(c + 20,x5);
U32TO8_LITTLE(c + 24,x6);
U32TO8_LITTLE(c + 28,x7);
U32TO8_LITTLE(c + 32,x8);
U32TO8_LITTLE(c + 36,x9);
U32TO8_LITTLE(c + 40,x10);
U32TO8_LITTLE(c + 44,x11);
U32TO8_LITTLE(c + 48,x12);
U32TO8_LITTLE(c + 52,x13);
U32TO8_LITTLE(c + 56,x14);
U32TO8_LITTLE(c + 60,x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
m += 64;
}
}

View File

@@ -0,0 +1,35 @@
/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#ifndef CHACHA_H
#define CHACHA_H
#include <sys/types.h>
struct chacha_ctx {
u_int input[16];
};
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits)
__attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr)
__attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
__attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)));
void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
u_char *c, u_int bytes)
__attribute__((__bounded__(__buffer__, 2, 4)))
__attribute__((__bounded__(__buffer__, 3, 4)));
#endif /* CHACHA_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,315 @@
/* $OpenBSD: channels.h,v 1.118 2015/07/01 02:26:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* 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".
*/
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CHANNEL_H
#define CHANNEL_H
/* Definitions for channel types. */
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */
#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
#define SSH_CHANNEL_LARVAL 10 /* larval session */
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
#define SSH_CHANNEL_CONNECTING 12
#define SSH_CHANNEL_DYNAMIC 13
#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
#define SSH_CHANNEL_MAX_TYPE 20
#define CHANNEL_CANCEL_PORT_STATIC -1
struct Channel;
typedef struct Channel Channel;
typedef void channel_open_fn(int, int, void *);
typedef void channel_callback_fn(int, void *);
typedef int channel_infilter_fn(struct Channel *, char *, int);
typedef void channel_filter_cleanup_fn(int, void *);
typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *);
/* Channel success/failure callbacks */
typedef void channel_confirm_cb(int, struct Channel *, void *);
typedef void channel_confirm_abandon_cb(struct Channel *, void *);
struct channel_confirm {
TAILQ_ENTRY(channel_confirm) entry;
channel_confirm_cb *cb;
channel_confirm_abandon_cb *abandon_cb;
void *ctx;
};
TAILQ_HEAD(channel_confirms, channel_confirm);
/* Context for non-blocking connects */
struct channel_connect {
char *host;
int port;
struct addrinfo *ai, *aitop;
};
/* Callbacks for mux channels back into client-specific code */
typedef int mux_callback_fn(struct Channel *);
struct Channel {
int type; /* channel type/state */
int self; /* my own channel identifier */
int remote_id; /* channel identifier for remote peer */
u_int istate; /* input from channel (state of receive half) */
u_int ostate; /* output to channel (state of transmit half) */
int flags; /* close sent/rcvd */
int rfd; /* read fd */
int wfd; /* write fd */
int efd; /* extended fd */
int sock; /* sock fd */
int ctl_chan; /* control channel (multiplexed connections) */
int isatty; /* rfd is a tty */
#ifdef _AIX
int wfd_isatty; /* wfd is a tty */
#endif
int client_tty; /* (client) TTY has been requested */
int force_drain; /* force close on iEOF */
time_t notbefore; /* Pause IO until deadline (time_t) */
int delayed; /* post-select handlers for newly created
* channels are delayed until the first call
* to a matching pre-select handler.
* this way post-select handlers are not
* accidentally called if a FD gets reused */
Buffer input; /* data read from socket, to be sent over
* encrypted connection */
Buffer output; /* data received over encrypted connection for
* send on socket */
Buffer extended;
char *path;
/* path for unix domain sockets, or host name for forwards */
int listening_port; /* port being listened for forwards */
char *listening_addr; /* addr being listened for forwards */
int host_port; /* remote port to connect for forwards */
char *remote_name; /* remote hostname */
u_int remote_window;
u_int remote_maxpacket;
u_int local_window;
u_int local_window_max;
u_int local_consumed;
u_int local_maxpacket;
int extended_usage;
int single_connection;
char *ctype; /* type */
/* callback */
channel_open_fn *open_confirm;
void *open_confirm_ctx;
channel_callback_fn *detach_user;
int detach_close;
struct channel_confirms status_confirms;
/* filter */
channel_infilter_fn *input_filter;
channel_outfilter_fn *output_filter;
void *filter_ctx;
channel_filter_cleanup_fn *filter_cleanup;
/* keep boundaries */
int datagram;
/* non-blocking connect */
struct channel_connect connect_ctx;
/* multiplexing protocol hook, called for each packet received */
mux_callback_fn *mux_rcb;
void *mux_ctx;
int mux_pause;
};
#define CHAN_EXTENDED_IGNORE 0
#define CHAN_EXTENDED_READ 1
#define CHAN_EXTENDED_WRITE 2
/* default window/packet sizes for tcp/x11-fwd-channel */
#define CHAN_SES_PACKET_DEFAULT (32*1024)
#define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT)
#define CHAN_TCP_PACKET_DEFAULT (32*1024)
#define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT)
#define CHAN_X11_PACKET_DEFAULT (16*1024)
#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT)
/* possible input states */
#define CHAN_INPUT_OPEN 0
#define CHAN_INPUT_WAIT_DRAIN 1
#define CHAN_INPUT_WAIT_OCLOSE 2
#define CHAN_INPUT_CLOSED 3
/* possible output states */
#define CHAN_OUTPUT_OPEN 0
#define CHAN_OUTPUT_WAIT_DRAIN 1
#define CHAN_OUTPUT_WAIT_IEOF 2
#define CHAN_OUTPUT_CLOSED 3
#define CHAN_CLOSE_SENT 0x01
#define CHAN_CLOSE_RCVD 0x02
#define CHAN_EOF_SENT 0x04
#define CHAN_EOF_RCVD 0x08
#define CHAN_LOCAL 0x10
#define CHAN_RBUF 16*1024
/* check whether 'efd' is still in use */
#define CHANNEL_EFD_INPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
(c->efd != -1 || \
buffer_len(&c->extended) > 0))
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \
buffer_len(&c->extended) > 0))
/* channel management */
Channel *channel_by_id(int);
Channel *channel_lookup(int);
Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
void channel_set_fds(int, int, int, int, int, int, int, u_int);
void channel_free(Channel *);
void channel_free_all(void);
void channel_stop_listening(void);
void channel_send_open(int);
void channel_request_start(int, char *, int);
void channel_register_cleanup(int, channel_callback_fn *, int);
void channel_register_open_confirm(int, channel_open_fn *, void *);
void channel_register_filter(int, channel_infilter_fn *,
channel_outfilter_fn *, channel_filter_cleanup_fn *, void *);
void channel_register_status_confirm(int, channel_confirm_cb *,
channel_confirm_abandon_cb *, void *);
void channel_cancel_cleanup(int);
int channel_close_fd(int *);
void channel_send_window_changes(void);
/* protocol handler */
int channel_input_close(int, u_int32_t, void *);
int channel_input_close_confirmation(int, u_int32_t, void *);
int channel_input_data(int, u_int32_t, void *);
int channel_input_extended_data(int, u_int32_t, void *);
int channel_input_ieof(int, u_int32_t, void *);
int channel_input_oclose(int, u_int32_t, void *);
int channel_input_open_confirmation(int, u_int32_t, void *);
int channel_input_open_failure(int, u_int32_t, void *);
int channel_input_port_open(int, u_int32_t, void *);
int channel_input_window_adjust(int, u_int32_t, void *);
int channel_input_status_confirm(int, u_int32_t, void *);
/* file descriptor handling (read/write) */
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*,
time_t*, int);
void channel_after_select(fd_set *, fd_set *);
void channel_output_poll(void);
int channel_not_very_much_buffered_data(void);
void channel_close_all(void);
int channel_still_open(void);
char *channel_open_message(void);
int channel_find_open(void);
/* tcp forwarding */
struct Forward;
struct ForwardOptions;
void channel_set_af(int af);
void channel_permit_all_opens(void);
void channel_add_permitted_opens(char *, int);
int channel_add_adm_permitted_opens(char *, int);
void channel_disable_adm_local_opens(void);
void channel_update_permitted_opens(int, int);
void channel_clear_permitted_opens(void);
void channel_clear_adm_permitted_opens(void);
void channel_print_adm_permitted_opens(void);
int channel_input_port_forward_request(int, struct ForwardOptions *);
Channel *channel_connect_to_port(const char *, u_short, char *, char *);
Channel *channel_connect_to_path(const char *, char *, char *);
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
Channel *channel_connect_by_listen_address(const char *, u_short,
char *, char *);
Channel *channel_connect_by_listen_path(const char *, char *, char *);
int channel_request_remote_forwarding(struct Forward *);
int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
int channel_request_rforward_cancel(struct Forward *);
int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
int channel_cancel_rport_listener(struct Forward *);
int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
int permitopen_port(const char *);
/* x11 forwarding */
void channel_set_x11_refuse_time(u_int);
int x11_connect_display(void);
int x11_create_display_inet(int, int, int, u_int *, int **);
int x11_input_open(int, u_int32_t, void *);
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
const char *, int);
int deny_input_open(int, u_int32_t, void *);
/* agent forwarding */
void auth_request_forwarding(void);
/* channel close */
int chan_is_dead(Channel *, int);
void chan_mark_dead(Channel *);
/* channel events */
void chan_rcvd_oclose(Channel *);
void chan_rcvd_eow(Channel *); /* SSH2-only */
void chan_read_failed(Channel *);
void chan_ibuf_empty(Channel *);
void chan_rcvd_ieof(Channel *);
void chan_write_failed(Channel *);
void chan_obuf_empty(Channel *);
#endif

View File

@@ -0,0 +1,155 @@
/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <openssl/evp.h>
#include "ssherr.h"
/*
* This is used by SSH1:
*
* What kind of triple DES are these 2 routines?
*
* Why is there a redundant initialization vector?
*
* If only iv3 was used, then, this would till effect have been
* outer-cbc. However, there is also a private iv1 == iv2 which
* perhaps makes differential analysis easier. On the other hand, the
* private iv1 probably makes the CRC-32 attack ineffective. This is a
* result of that there is no longer any known iv1 to use when
* choosing the X block.
*/
struct ssh1_3des_ctx
{
EVP_CIPHER_CTX k1, k2, k3;
};
const EVP_CIPHER * evp_ssh1_3des(void);
int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
static int
ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
int enc)
{
struct ssh1_3des_ctx *c;
u_char *k1, *k2, *k3;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
if ((c = calloc(1, sizeof(*c))) == NULL)
return 0;
EVP_CIPHER_CTX_set_app_data(ctx, c);
}
if (key == NULL)
return 1;
if (enc == -1)
enc = ctx->encrypt;
k1 = k2 = k3 = (u_char *) key;
k2 += 8;
if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
if (enc)
k3 += 16;
else
k1 += 16;
}
EVP_CIPHER_CTX_init(&c->k1);
EVP_CIPHER_CTX_init(&c->k2);
EVP_CIPHER_CTX_init(&c->k3);
if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
explicit_bzero(c, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
return 0;
}
return 1;
}
static int
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
{
struct ssh1_3des_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
return 0;
if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
EVP_Cipher(&c->k3, dest, dest, len) == 0)
return 0;
return 1;
}
static int
ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
{
struct ssh1_3des_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
EVP_CIPHER_CTX_cleanup(&c->k1);
EVP_CIPHER_CTX_cleanup(&c->k2);
EVP_CIPHER_CTX_cleanup(&c->k3);
explicit_bzero(c, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
}
return 1;
}
int
ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
{
struct ssh1_3des_ctx *c;
if (len != 24)
return SSH_ERR_INVALID_ARGUMENT;
if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
return SSH_ERR_INTERNAL_ERROR;
if (doset) {
memcpy(c->k1.iv, iv, 8);
memcpy(c->k2.iv, iv + 8, 8);
memcpy(c->k3.iv, iv + 16, 8);
} else {
memcpy(iv, c->k1.iv, 8);
memcpy(iv + 8, c->k2.iv, 8);
memcpy(iv + 16, c->k3.iv, 8);
}
return 0;
}
const EVP_CIPHER *
evp_ssh1_3des(void)
{
static EVP_CIPHER ssh1_3des;
memset(&ssh1_3des, 0, sizeof(ssh1_3des));
ssh1_3des.nid = NID_undef;
ssh1_3des.block_size = 8;
ssh1_3des.iv_len = 0;
ssh1_3des.key_len = 16;
ssh1_3des.init = ssh1_3des_init;
ssh1_3des.cleanup = ssh1_3des_cleanup;
ssh1_3des.do_cipher = ssh1_3des_cbc;
ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
return &ssh1_3des;
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
#ifdef USE_BUILTIN_RIJNDAEL
#include <sys/types.h>
#include <openssl/evp.h>
#include <stdarg.h>
#include <string.h>
#include "rijndael.h"
#include "xmalloc.h"
#include "log.h"
#define RIJNDAEL_BLOCKSIZE 16
struct ssh_rijndael_ctx
{
rijndael_ctx r_ctx;
u_char r_iv[RIJNDAEL_BLOCKSIZE];
};
static int
ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
int enc)
{
struct ssh_rijndael_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
c = xmalloc(sizeof(*c));
EVP_CIPHER_CTX_set_app_data(ctx, c);
}
if (key != NULL) {
if (enc == -1)
enc = ctx->encrypt;
rijndael_set_key(&c->r_ctx, (u_char *)key,
8*EVP_CIPHER_CTX_key_length(ctx), enc);
}
if (iv != NULL)
memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
return (1);
}
static int
ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
LIBCRYPTO_EVP_INL_TYPE len)
{
struct ssh_rijndael_ctx *c;
u_char buf[RIJNDAEL_BLOCKSIZE];
u_char *cprev, *cnow, *plain, *ivp;
int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
if (len == 0)
return (1);
if (len % RIJNDAEL_BLOCKSIZE)
fatal("ssh_rijndael_cbc: bad len %d", len);
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
error("ssh_rijndael_cbc: no context");
return (0);
}
if (ctx->encrypt) {
cnow = dest;
plain = (u_char *)src;
cprev = c->r_iv;
for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
cnow+=RIJNDAEL_BLOCKSIZE) {
for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
buf[j] = plain[j] ^ cprev[j];
rijndael_encrypt(&c->r_ctx, buf, cnow);
cprev = cnow;
}
memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
} else {
cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
plain = dest+len-RIJNDAEL_BLOCKSIZE;
memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
plain-=RIJNDAEL_BLOCKSIZE) {
rijndael_decrypt(&c->r_ctx, cnow, plain);
ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
plain[j] ^= ivp[j];
}
memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
}
return (1);
}
static int
ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
{
struct ssh_rijndael_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
memset(c, 0, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
}
return (1);
}
void
ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
{
struct ssh_rijndael_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
fatal("ssh_rijndael_iv: no context");
if (doset)
memcpy(c->r_iv, iv, len);
else
memcpy(iv, c->r_iv, len);
}
const EVP_CIPHER *
evp_rijndael(void)
{
static EVP_CIPHER rijndal_cbc;
memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
rijndal_cbc.nid = NID_undef;
rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
rijndal_cbc.key_len = 16;
rijndal_cbc.init = ssh_rijndael_init;
rijndal_cbc.cleanup = ssh_rijndael_cleanup;
rijndal_cbc.do_cipher = ssh_rijndael_cbc;
#ifndef SSH_OLD_EVP
rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
#endif
return (&rijndal_cbc);
}
#endif /* USE_BUILTIN_RIJNDAEL */

View File

@@ -0,0 +1,83 @@
/* $OpenBSD: cipher-aesctr.c,v 1.2 2015/01/14 10:24:42 markus Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#ifndef WITH_OPENSSL
#include "cipher-aesctr.h"
/*
* increment counter 'ctr',
* the counter is of size 'len' bytes and stored in network-byte-order.
* (LSB at ctr[len-1], MSB at ctr[0])
*/
static inline void
aesctr_inc(u8 *ctr, u32 len)
{
ssize_t i;
#ifndef CONSTANT_TIME_INCREMENT
for (i = len - 1; i >= 0; i--)
if (++ctr[i]) /* continue on overflow */
return;
#else
u8 x, add = 1;
for (i = len - 1; i >= 0; i--) {
ctr[i] += add;
/* constant time for: x = ctr[i] ? 1 : 0 */
x = ctr[i];
x = (x | (x >> 4)) & 0xf;
x = (x | (x >> 2)) & 0x3;
x = (x | (x >> 1)) & 0x1;
add *= (x^1);
}
#endif
}
void
aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
x->rounds = rijndaelKeySetupEnc(x->ek, k, kbits);
}
void
aesctr_ivsetup(aesctr_ctx *x,const u8 *iv)
{
memcpy(x->ctr, iv, AES_BLOCK_SIZE);
}
void
aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 n = 0;
u8 buf[AES_BLOCK_SIZE];
while ((bytes--) > 0) {
if (n == 0) {
rijndaelEncrypt(x->ek, x->rounds, x->ctr, buf);
aesctr_inc(x->ctr, AES_BLOCK_SIZE);
}
*(c++) = *(m++) ^ buf[n];
n = (n + 1) % AES_BLOCK_SIZE;
}
}
#endif /* !WITH_OPENSSL */

View File

@@ -0,0 +1,35 @@
/* $OpenBSD: cipher-aesctr.h,v 1.1 2014/04/29 15:39:33 markus Exp $ */
/*
* Copyright (c) 2014 Markus Friedl
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef OPENSSH_AESCTR_H
#define OPENSSH_AESCTR_H
#include "rijndael.h"
#define AES_BLOCK_SIZE 16
typedef struct aesctr_ctx {
int rounds; /* keylen-dependent #rounds */
u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
u8 ctr[AES_BLOCK_SIZE]; /* counter */
} aesctr_ctx;
void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits);
void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv);
void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes);
#endif

Some files were not shown because too many files have changed in this diff Show More