1*8e28d849SEd Maste /* $OpenBSD: sshd-auth.c,v 1.3 2025/01/16 06:37:10 dtucker Exp $ */
2*8e28d849SEd Maste /*
3*8e28d849SEd Maste * SSH2 implementation:
4*8e28d849SEd Maste * Privilege Separation:
5*8e28d849SEd Maste *
6*8e28d849SEd Maste * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
7*8e28d849SEd Maste * Copyright (c) 2002 Niels Provos. All rights reserved.
8*8e28d849SEd Maste *
9*8e28d849SEd Maste * Redistribution and use in source and binary forms, with or without
10*8e28d849SEd Maste * modification, are permitted provided that the following conditions
11*8e28d849SEd Maste * are met:
12*8e28d849SEd Maste * 1. Redistributions of source code must retain the above copyright
13*8e28d849SEd Maste * notice, this list of conditions and the following disclaimer.
14*8e28d849SEd Maste * 2. Redistributions in binary form must reproduce the above copyright
15*8e28d849SEd Maste * notice, this list of conditions and the following disclaimer in the
16*8e28d849SEd Maste * documentation and/or other materials provided with the distribution.
17*8e28d849SEd Maste *
18*8e28d849SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*8e28d849SEd Maste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*8e28d849SEd Maste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*8e28d849SEd Maste * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*8e28d849SEd Maste * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*8e28d849SEd Maste * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*8e28d849SEd Maste * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*8e28d849SEd Maste * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*8e28d849SEd Maste * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*8e28d849SEd Maste * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*8e28d849SEd Maste */
29*8e28d849SEd Maste
30*8e28d849SEd Maste #include "includes.h"
31*8e28d849SEd Maste
32*8e28d849SEd Maste #include <sys/types.h>
33*8e28d849SEd Maste #include <sys/ioctl.h>
34*8e28d849SEd Maste #include <sys/wait.h>
35*8e28d849SEd Maste #include <sys/stat.h>
36*8e28d849SEd Maste #include <sys/socket.h>
37*8e28d849SEd Maste #include <sys/time.h>
38*8e28d849SEd Maste
39*8e28d849SEd Maste #include "openbsd-compat/sys-tree.h"
40*8e28d849SEd Maste #include "openbsd-compat/sys-queue.h"
41*8e28d849SEd Maste
42*8e28d849SEd Maste #include <errno.h>
43*8e28d849SEd Maste #include <fcntl.h>
44*8e28d849SEd Maste #include <netdb.h>
45*8e28d849SEd Maste #ifdef HAVE_PATHS_H
46*8e28d849SEd Maste # include <paths.h>
47*8e28d849SEd Maste #endif
48*8e28d849SEd Maste #include <pwd.h>
49*8e28d849SEd Maste #include <grp.h>
50*8e28d849SEd Maste #include <signal.h>
51*8e28d849SEd Maste #include <stdio.h>
52*8e28d849SEd Maste #include <stdlib.h>
53*8e28d849SEd Maste #include <string.h>
54*8e28d849SEd Maste #include <stdarg.h>
55*8e28d849SEd Maste #include <unistd.h>
56*8e28d849SEd Maste #include <limits.h>
57*8e28d849SEd Maste
58*8e28d849SEd Maste #ifdef WITH_OPENSSL
59*8e28d849SEd Maste #include <openssl/bn.h>
60*8e28d849SEd Maste #include <openssl/evp.h>
61*8e28d849SEd Maste #endif
62*8e28d849SEd Maste
63*8e28d849SEd Maste #include "xmalloc.h"
64*8e28d849SEd Maste #include "ssh.h"
65*8e28d849SEd Maste #include "ssh2.h"
66*8e28d849SEd Maste #include "sshpty.h"
67*8e28d849SEd Maste #include "packet.h"
68*8e28d849SEd Maste #include "log.h"
69*8e28d849SEd Maste #include "sshbuf.h"
70*8e28d849SEd Maste #include "misc.h"
71*8e28d849SEd Maste #include "match.h"
72*8e28d849SEd Maste #include "servconf.h"
73*8e28d849SEd Maste #include "uidswap.h"
74*8e28d849SEd Maste #include "compat.h"
75*8e28d849SEd Maste #include "cipher.h"
76*8e28d849SEd Maste #include "digest.h"
77*8e28d849SEd Maste #include "sshkey.h"
78*8e28d849SEd Maste #include "kex.h"
79*8e28d849SEd Maste #include "authfile.h"
80*8e28d849SEd Maste #include "pathnames.h"
81*8e28d849SEd Maste #include "atomicio.h"
82*8e28d849SEd Maste #include "canohost.h"
83*8e28d849SEd Maste #include "hostfile.h"
84*8e28d849SEd Maste #include "auth.h"
85*8e28d849SEd Maste #include "authfd.h"
86*8e28d849SEd Maste #include "msg.h"
87*8e28d849SEd Maste #include "dispatch.h"
88*8e28d849SEd Maste #include "channels.h"
89*8e28d849SEd Maste #include "session.h"
90*8e28d849SEd Maste #include "monitor.h"
91*8e28d849SEd Maste #ifdef GSSAPI
92*8e28d849SEd Maste #include "ssh-gss.h"
93*8e28d849SEd Maste #endif
94*8e28d849SEd Maste #include "monitor_wrap.h"
95*8e28d849SEd Maste #include "auth-options.h"
96*8e28d849SEd Maste #include "version.h"
97*8e28d849SEd Maste #include "ssherr.h"
98*8e28d849SEd Maste #include "sk-api.h"
99*8e28d849SEd Maste #include "srclimit.h"
100*8e28d849SEd Maste #include "ssh-sandbox.h"
101*8e28d849SEd Maste #include "dh.h"
102*8e28d849SEd Maste
103*8e28d849SEd Maste /* Privsep fds */
104*8e28d849SEd Maste #define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1)
105*8e28d849SEd Maste #define PRIVSEP_LOG_FD (STDERR_FILENO + 2)
106*8e28d849SEd Maste #define PRIVSEP_MIN_FREE_FD (STDERR_FILENO + 3)
107*8e28d849SEd Maste
108*8e28d849SEd Maste extern char *__progname;
109*8e28d849SEd Maste
110*8e28d849SEd Maste /* Server configuration options. */
111*8e28d849SEd Maste ServerOptions options;
112*8e28d849SEd Maste
113*8e28d849SEd Maste /* Name of the server configuration file. */
114*8e28d849SEd Maste char *config_file_name = _PATH_SERVER_CONFIG_FILE;
115*8e28d849SEd Maste
116*8e28d849SEd Maste /*
117*8e28d849SEd Maste * Debug mode flag. This can be set on the command line. If debug
118*8e28d849SEd Maste * mode is enabled, extra debugging output will be sent to the system
119*8e28d849SEd Maste * log, the daemon will not go to background, and will exit after processing
120*8e28d849SEd Maste * the first connection.
121*8e28d849SEd Maste */
122*8e28d849SEd Maste int debug_flag = 0;
123*8e28d849SEd Maste
124*8e28d849SEd Maste /* Flag indicating that the daemon is being started from inetd. */
125*8e28d849SEd Maste static int inetd_flag = 0;
126*8e28d849SEd Maste
127*8e28d849SEd Maste /* Saved arguments to main(). */
128*8e28d849SEd Maste static char **saved_argv;
129*8e28d849SEd Maste static int saved_argc;
130*8e28d849SEd Maste
131*8e28d849SEd Maste
132*8e28d849SEd Maste /* Daemon's agent connection */
133*8e28d849SEd Maste int auth_sock = -1;
134*8e28d849SEd Maste static int have_agent = 0;
135*8e28d849SEd Maste
136*8e28d849SEd Maste u_int num_hostkeys;
137*8e28d849SEd Maste struct sshkey **host_pubkeys; /* all public host keys */
138*8e28d849SEd Maste struct sshkey **host_certificates; /* all public host certificates */
139*8e28d849SEd Maste
140*8e28d849SEd Maste /* record remote hostname or ip */
141*8e28d849SEd Maste u_int utmp_len = HOST_NAME_MAX+1;
142*8e28d849SEd Maste
143*8e28d849SEd Maste /* variables used for privilege separation */
144*8e28d849SEd Maste struct monitor *pmonitor = NULL;
145*8e28d849SEd Maste int privsep_is_preauth = 1;
146*8e28d849SEd Maste static int privsep_chroot = 1;
147*8e28d849SEd Maste
148*8e28d849SEd Maste /* global connection state and authentication contexts */
149*8e28d849SEd Maste Authctxt *the_authctxt = NULL;
150*8e28d849SEd Maste struct ssh *the_active_state;
151*8e28d849SEd Maste
152*8e28d849SEd Maste /* global key/cert auth options. XXX move to permanent ssh->authctxt? */
153*8e28d849SEd Maste struct sshauthopt *auth_opts = NULL;
154*8e28d849SEd Maste
155*8e28d849SEd Maste /* sshd_config buffer */
156*8e28d849SEd Maste struct sshbuf *cfg;
157*8e28d849SEd Maste
158*8e28d849SEd Maste /* Included files from the configuration file */
159*8e28d849SEd Maste struct include_list includes = TAILQ_HEAD_INITIALIZER(includes);
160*8e28d849SEd Maste
161*8e28d849SEd Maste /* message to be displayed after login */
162*8e28d849SEd Maste struct sshbuf *loginmsg;
163*8e28d849SEd Maste
164*8e28d849SEd Maste /* Prototypes for various functions defined later in this file. */
165*8e28d849SEd Maste static void do_ssh2_kex(struct ssh *);
166*8e28d849SEd Maste
167*8e28d849SEd Maste /* Unprivileged user */
168*8e28d849SEd Maste struct passwd *privsep_pw = NULL;
169*8e28d849SEd Maste
170*8e28d849SEd Maste #ifndef HAVE_PLEDGE
171*8e28d849SEd Maste static struct ssh_sandbox *box;
172*8e28d849SEd Maste #endif
173*8e28d849SEd Maste
174*8e28d849SEd Maste /* XXX stub */
175*8e28d849SEd Maste int
mm_is_monitor(void)176*8e28d849SEd Maste mm_is_monitor(void)
177*8e28d849SEd Maste {
178*8e28d849SEd Maste return 0;
179*8e28d849SEd Maste }
180*8e28d849SEd Maste
181*8e28d849SEd Maste static void
privsep_child_demote(void)182*8e28d849SEd Maste privsep_child_demote(void)
183*8e28d849SEd Maste {
184*8e28d849SEd Maste gid_t gidset[1];
185*8e28d849SEd Maste
186*8e28d849SEd Maste #ifndef HAVE_PLEDGE
187*8e28d849SEd Maste if ((box = ssh_sandbox_init(pmonitor)) == NULL)
188*8e28d849SEd Maste fatal_f("ssh_sandbox_init failed");
189*8e28d849SEd Maste #endif
190*8e28d849SEd Maste /* Demote the child */
191*8e28d849SEd Maste if (privsep_chroot) {
192*8e28d849SEd Maste /* Change our root directory */
193*8e28d849SEd Maste if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
194*8e28d849SEd Maste fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
195*8e28d849SEd Maste strerror(errno));
196*8e28d849SEd Maste if (chdir("/") == -1)
197*8e28d849SEd Maste fatal("chdir(\"/\"): %s", strerror(errno));
198*8e28d849SEd Maste
199*8e28d849SEd Maste /*
200*8e28d849SEd Maste * Drop our privileges
201*8e28d849SEd Maste * NB. Can't use setusercontext() after chroot.
202*8e28d849SEd Maste */
203*8e28d849SEd Maste debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
204*8e28d849SEd Maste (u_int)privsep_pw->pw_gid);
205*8e28d849SEd Maste gidset[0] = privsep_pw->pw_gid;
206*8e28d849SEd Maste if (setgroups(1, gidset) == -1)
207*8e28d849SEd Maste fatal("setgroups: %.100s", strerror(errno));
208*8e28d849SEd Maste permanently_set_uid(privsep_pw);
209*8e28d849SEd Maste }
210*8e28d849SEd Maste
211*8e28d849SEd Maste /* sandbox ourselves */
212*8e28d849SEd Maste #ifdef HAVE_PLEDGE
213*8e28d849SEd Maste if (pledge("stdio", NULL) == -1)
214*8e28d849SEd Maste fatal_f("pledge()");
215*8e28d849SEd Maste #else
216*8e28d849SEd Maste ssh_sandbox_child(box);
217*8e28d849SEd Maste #endif
218*8e28d849SEd Maste }
219*8e28d849SEd Maste
220*8e28d849SEd Maste static void
append_hostkey_type(struct sshbuf * b,const char * s)221*8e28d849SEd Maste append_hostkey_type(struct sshbuf *b, const char *s)
222*8e28d849SEd Maste {
223*8e28d849SEd Maste int r;
224*8e28d849SEd Maste
225*8e28d849SEd Maste if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
226*8e28d849SEd Maste debug3_f("%s key not permitted by HostkeyAlgorithms", s);
227*8e28d849SEd Maste return;
228*8e28d849SEd Maste }
229*8e28d849SEd Maste if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
230*8e28d849SEd Maste fatal_fr(r, "sshbuf_putf");
231*8e28d849SEd Maste }
232*8e28d849SEd Maste
233*8e28d849SEd Maste static char *
list_hostkey_types(void)234*8e28d849SEd Maste list_hostkey_types(void)
235*8e28d849SEd Maste {
236*8e28d849SEd Maste struct sshbuf *b;
237*8e28d849SEd Maste struct sshkey *key;
238*8e28d849SEd Maste char *ret;
239*8e28d849SEd Maste u_int i;
240*8e28d849SEd Maste
241*8e28d849SEd Maste if ((b = sshbuf_new()) == NULL)
242*8e28d849SEd Maste fatal_f("sshbuf_new failed");
243*8e28d849SEd Maste for (i = 0; i < options.num_host_key_files; i++) {
244*8e28d849SEd Maste key = host_pubkeys[i];
245*8e28d849SEd Maste if (key == NULL)
246*8e28d849SEd Maste continue;
247*8e28d849SEd Maste switch (key->type) {
248*8e28d849SEd Maste case KEY_RSA:
249*8e28d849SEd Maste /* for RSA we also support SHA2 signatures */
250*8e28d849SEd Maste append_hostkey_type(b, "rsa-sha2-512");
251*8e28d849SEd Maste append_hostkey_type(b, "rsa-sha2-256");
252*8e28d849SEd Maste /* FALLTHROUGH */
253*8e28d849SEd Maste case KEY_DSA:
254*8e28d849SEd Maste case KEY_ECDSA:
255*8e28d849SEd Maste case KEY_ED25519:
256*8e28d849SEd Maste case KEY_ECDSA_SK:
257*8e28d849SEd Maste case KEY_ED25519_SK:
258*8e28d849SEd Maste case KEY_XMSS:
259*8e28d849SEd Maste append_hostkey_type(b, sshkey_ssh_name(key));
260*8e28d849SEd Maste break;
261*8e28d849SEd Maste }
262*8e28d849SEd Maste /* If the private key has a cert peer, then list that too */
263*8e28d849SEd Maste key = host_certificates[i];
264*8e28d849SEd Maste if (key == NULL)
265*8e28d849SEd Maste continue;
266*8e28d849SEd Maste switch (key->type) {
267*8e28d849SEd Maste case KEY_RSA_CERT:
268*8e28d849SEd Maste /* for RSA we also support SHA2 signatures */
269*8e28d849SEd Maste append_hostkey_type(b,
270*8e28d849SEd Maste "rsa-sha2-512-cert-v01@openssh.com");
271*8e28d849SEd Maste append_hostkey_type(b,
272*8e28d849SEd Maste "rsa-sha2-256-cert-v01@openssh.com");
273*8e28d849SEd Maste /* FALLTHROUGH */
274*8e28d849SEd Maste case KEY_DSA_CERT:
275*8e28d849SEd Maste case KEY_ECDSA_CERT:
276*8e28d849SEd Maste case KEY_ED25519_CERT:
277*8e28d849SEd Maste case KEY_ECDSA_SK_CERT:
278*8e28d849SEd Maste case KEY_ED25519_SK_CERT:
279*8e28d849SEd Maste case KEY_XMSS_CERT:
280*8e28d849SEd Maste append_hostkey_type(b, sshkey_ssh_name(key));
281*8e28d849SEd Maste break;
282*8e28d849SEd Maste }
283*8e28d849SEd Maste }
284*8e28d849SEd Maste if ((ret = sshbuf_dup_string(b)) == NULL)
285*8e28d849SEd Maste fatal_f("sshbuf_dup_string failed");
286*8e28d849SEd Maste sshbuf_free(b);
287*8e28d849SEd Maste debug_f("%s", ret);
288*8e28d849SEd Maste return ret;
289*8e28d849SEd Maste }
290*8e28d849SEd Maste
291*8e28d849SEd Maste struct sshkey *
get_hostkey_public_by_type(int type,int nid,struct ssh * ssh)292*8e28d849SEd Maste get_hostkey_public_by_type(int type, int nid, struct ssh *ssh)
293*8e28d849SEd Maste {
294*8e28d849SEd Maste u_int i;
295*8e28d849SEd Maste struct sshkey *key;
296*8e28d849SEd Maste
297*8e28d849SEd Maste for (i = 0; i < options.num_host_key_files; i++) {
298*8e28d849SEd Maste switch (type) {
299*8e28d849SEd Maste case KEY_RSA_CERT:
300*8e28d849SEd Maste case KEY_DSA_CERT:
301*8e28d849SEd Maste case KEY_ECDSA_CERT:
302*8e28d849SEd Maste case KEY_ED25519_CERT:
303*8e28d849SEd Maste case KEY_ECDSA_SK_CERT:
304*8e28d849SEd Maste case KEY_ED25519_SK_CERT:
305*8e28d849SEd Maste case KEY_XMSS_CERT:
306*8e28d849SEd Maste key = host_certificates[i];
307*8e28d849SEd Maste break;
308*8e28d849SEd Maste default:
309*8e28d849SEd Maste key = host_pubkeys[i];
310*8e28d849SEd Maste break;
311*8e28d849SEd Maste }
312*8e28d849SEd Maste if (key == NULL || key->type != type)
313*8e28d849SEd Maste continue;
314*8e28d849SEd Maste switch (type) {
315*8e28d849SEd Maste case KEY_ECDSA:
316*8e28d849SEd Maste case KEY_ECDSA_SK:
317*8e28d849SEd Maste case KEY_ECDSA_CERT:
318*8e28d849SEd Maste case KEY_ECDSA_SK_CERT:
319*8e28d849SEd Maste if (key->ecdsa_nid != nid)
320*8e28d849SEd Maste continue;
321*8e28d849SEd Maste /* FALLTHROUGH */
322*8e28d849SEd Maste default:
323*8e28d849SEd Maste return key;
324*8e28d849SEd Maste }
325*8e28d849SEd Maste }
326*8e28d849SEd Maste return NULL;
327*8e28d849SEd Maste }
328*8e28d849SEd Maste
329*8e28d849SEd Maste /* XXX remove */
330*8e28d849SEd Maste struct sshkey *
get_hostkey_private_by_type(int type,int nid,struct ssh * ssh)331*8e28d849SEd Maste get_hostkey_private_by_type(int type, int nid, struct ssh *ssh)
332*8e28d849SEd Maste {
333*8e28d849SEd Maste return NULL;
334*8e28d849SEd Maste }
335*8e28d849SEd Maste
336*8e28d849SEd Maste /* XXX remove */
337*8e28d849SEd Maste struct sshkey *
get_hostkey_by_index(int ind)338*8e28d849SEd Maste get_hostkey_by_index(int ind)
339*8e28d849SEd Maste {
340*8e28d849SEd Maste return NULL;
341*8e28d849SEd Maste }
342*8e28d849SEd Maste
343*8e28d849SEd Maste struct sshkey *
get_hostkey_public_by_index(int ind,struct ssh * ssh)344*8e28d849SEd Maste get_hostkey_public_by_index(int ind, struct ssh *ssh)
345*8e28d849SEd Maste {
346*8e28d849SEd Maste if (ind < 0 || (u_int)ind >= options.num_host_key_files)
347*8e28d849SEd Maste return (NULL);
348*8e28d849SEd Maste return host_pubkeys[ind];
349*8e28d849SEd Maste }
350*8e28d849SEd Maste
351*8e28d849SEd Maste int
get_hostkey_index(struct sshkey * key,int compare,struct ssh * ssh)352*8e28d849SEd Maste get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh)
353*8e28d849SEd Maste {
354*8e28d849SEd Maste u_int i;
355*8e28d849SEd Maste
356*8e28d849SEd Maste for (i = 0; i < options.num_host_key_files; i++) {
357*8e28d849SEd Maste if (sshkey_is_cert(key)) {
358*8e28d849SEd Maste if (key == host_certificates[i] ||
359*8e28d849SEd Maste (compare && host_certificates[i] &&
360*8e28d849SEd Maste sshkey_equal(key, host_certificates[i])))
361*8e28d849SEd Maste return (i);
362*8e28d849SEd Maste } else {
363*8e28d849SEd Maste if (key == host_pubkeys[i] ||
364*8e28d849SEd Maste (compare && host_pubkeys[i] &&
365*8e28d849SEd Maste sshkey_equal(key, host_pubkeys[i])))
366*8e28d849SEd Maste return (i);
367*8e28d849SEd Maste }
368*8e28d849SEd Maste }
369*8e28d849SEd Maste return (-1);
370*8e28d849SEd Maste }
371*8e28d849SEd Maste
372*8e28d849SEd Maste static void
usage(void)373*8e28d849SEd Maste usage(void)
374*8e28d849SEd Maste {
375*8e28d849SEd Maste fprintf(stderr, "%s, %s\n", SSH_VERSION, SSH_OPENSSL_VERSION);
376*8e28d849SEd Maste fprintf(stderr,
377*8e28d849SEd Maste "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n"
378*8e28d849SEd Maste " [-E log_file] [-f config_file] [-g login_grace_time]\n"
379*8e28d849SEd Maste " [-h host_key_file] [-o option] [-p port] [-u len]\n"
380*8e28d849SEd Maste );
381*8e28d849SEd Maste exit(1);
382*8e28d849SEd Maste }
383*8e28d849SEd Maste
384*8e28d849SEd Maste static void
parse_hostkeys(struct sshbuf * hostkeys)385*8e28d849SEd Maste parse_hostkeys(struct sshbuf *hostkeys)
386*8e28d849SEd Maste {
387*8e28d849SEd Maste int r;
388*8e28d849SEd Maste u_int num_keys = 0;
389*8e28d849SEd Maste struct sshkey *k;
390*8e28d849SEd Maste const u_char *cp;
391*8e28d849SEd Maste size_t len;
392*8e28d849SEd Maste
393*8e28d849SEd Maste while (sshbuf_len(hostkeys) != 0) {
394*8e28d849SEd Maste if (num_keys > 2048)
395*8e28d849SEd Maste fatal_f("too many hostkeys");
396*8e28d849SEd Maste host_pubkeys = xrecallocarray(host_pubkeys,
397*8e28d849SEd Maste num_keys, num_keys + 1, sizeof(*host_pubkeys));
398*8e28d849SEd Maste host_certificates = xrecallocarray(host_certificates,
399*8e28d849SEd Maste num_keys, num_keys + 1, sizeof(*host_certificates));
400*8e28d849SEd Maste /* public key */
401*8e28d849SEd Maste k = NULL;
402*8e28d849SEd Maste if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0)
403*8e28d849SEd Maste fatal_fr(r, "extract pubkey");
404*8e28d849SEd Maste if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0)
405*8e28d849SEd Maste fatal_fr(r, "parse pubkey");
406*8e28d849SEd Maste host_pubkeys[num_keys] = k;
407*8e28d849SEd Maste if (k)
408*8e28d849SEd Maste debug2_f("key %u: %s", num_keys, sshkey_ssh_name(k));
409*8e28d849SEd Maste /* certificate */
410*8e28d849SEd Maste k = NULL;
411*8e28d849SEd Maste if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0)
412*8e28d849SEd Maste fatal_fr(r, "extract pubkey");
413*8e28d849SEd Maste if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0)
414*8e28d849SEd Maste fatal_fr(r, "parse pubkey");
415*8e28d849SEd Maste host_certificates[num_keys] = k;
416*8e28d849SEd Maste if (k)
417*8e28d849SEd Maste debug2_f("cert %u: %s", num_keys, sshkey_ssh_name(k));
418*8e28d849SEd Maste num_keys++;
419*8e28d849SEd Maste }
420*8e28d849SEd Maste num_hostkeys = num_keys;
421*8e28d849SEd Maste }
422*8e28d849SEd Maste
423*8e28d849SEd Maste static void
recv_privsep_state(struct ssh * ssh,struct sshbuf * conf,uint64_t * timing_secretp)424*8e28d849SEd Maste recv_privsep_state(struct ssh *ssh, struct sshbuf *conf,
425*8e28d849SEd Maste uint64_t *timing_secretp)
426*8e28d849SEd Maste {
427*8e28d849SEd Maste struct sshbuf *hostkeys;
428*8e28d849SEd Maste
429*8e28d849SEd Maste debug3_f("begin");
430*8e28d849SEd Maste
431*8e28d849SEd Maste mm_get_state(ssh, &includes, conf, NULL, timing_secretp,
432*8e28d849SEd Maste &hostkeys, NULL, NULL, NULL, NULL);
433*8e28d849SEd Maste parse_hostkeys(hostkeys);
434*8e28d849SEd Maste
435*8e28d849SEd Maste sshbuf_free(hostkeys);
436*8e28d849SEd Maste
437*8e28d849SEd Maste debug3_f("done");
438*8e28d849SEd Maste }
439*8e28d849SEd Maste
440*8e28d849SEd Maste /*
441*8e28d849SEd Maste * Main program for the daemon.
442*8e28d849SEd Maste */
443*8e28d849SEd Maste int
main(int ac,char ** av)444*8e28d849SEd Maste main(int ac, char **av)
445*8e28d849SEd Maste {
446*8e28d849SEd Maste struct ssh *ssh = NULL;
447*8e28d849SEd Maste extern char *optarg;
448*8e28d849SEd Maste extern int optind;
449*8e28d849SEd Maste int r, opt, have_key = 0;
450*8e28d849SEd Maste int sock_in = -1, sock_out = -1, rexeced_flag = 0;
451*8e28d849SEd Maste char *line, *logfile = NULL;
452*8e28d849SEd Maste u_int i;
453*8e28d849SEd Maste mode_t new_umask;
454*8e28d849SEd Maste Authctxt *authctxt;
455*8e28d849SEd Maste struct connection_info *connection_info = NULL;
456*8e28d849SEd Maste sigset_t sigmask;
457*8e28d849SEd Maste uint64_t timing_secret = 0;
458*8e28d849SEd Maste
459*8e28d849SEd Maste closefrom(PRIVSEP_MIN_FREE_FD);
460*8e28d849SEd Maste sigemptyset(&sigmask);
461*8e28d849SEd Maste sigprocmask(SIG_SETMASK, &sigmask, NULL);
462*8e28d849SEd Maste
463*8e28d849SEd Maste #ifdef HAVE_SECUREWARE
464*8e28d849SEd Maste (void)set_auth_parameters(ac, av);
465*8e28d849SEd Maste #endif
466*8e28d849SEd Maste __progname = ssh_get_progname(av[0]);
467*8e28d849SEd Maste
468*8e28d849SEd Maste /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
469*8e28d849SEd Maste saved_argc = ac;
470*8e28d849SEd Maste saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
471*8e28d849SEd Maste for (i = 0; (int)i < ac; i++)
472*8e28d849SEd Maste saved_argv[i] = xstrdup(av[i]);
473*8e28d849SEd Maste saved_argv[i] = NULL;
474*8e28d849SEd Maste
475*8e28d849SEd Maste seed_rng();
476*8e28d849SEd Maste
477*8e28d849SEd Maste #ifndef HAVE_SETPROCTITLE
478*8e28d849SEd Maste /* Prepare for later setproctitle emulation */
479*8e28d849SEd Maste compat_init_setproctitle(ac, av);
480*8e28d849SEd Maste av = saved_argv;
481*8e28d849SEd Maste #endif
482*8e28d849SEd Maste
483*8e28d849SEd Maste /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
484*8e28d849SEd Maste sanitise_stdfd();
485*8e28d849SEd Maste
486*8e28d849SEd Maste /* Initialize configuration options to their default values. */
487*8e28d849SEd Maste initialize_server_options(&options);
488*8e28d849SEd Maste
489*8e28d849SEd Maste /* Parse command-line arguments. */
490*8e28d849SEd Maste while ((opt = getopt(ac, av,
491*8e28d849SEd Maste "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) {
492*8e28d849SEd Maste switch (opt) {
493*8e28d849SEd Maste case '4':
494*8e28d849SEd Maste options.address_family = AF_INET;
495*8e28d849SEd Maste break;
496*8e28d849SEd Maste case '6':
497*8e28d849SEd Maste options.address_family = AF_INET6;
498*8e28d849SEd Maste break;
499*8e28d849SEd Maste case 'f':
500*8e28d849SEd Maste config_file_name = optarg;
501*8e28d849SEd Maste break;
502*8e28d849SEd Maste case 'c':
503*8e28d849SEd Maste servconf_add_hostcert("[command-line]", 0,
504*8e28d849SEd Maste &options, optarg);
505*8e28d849SEd Maste break;
506*8e28d849SEd Maste case 'd':
507*8e28d849SEd Maste if (debug_flag == 0) {
508*8e28d849SEd Maste debug_flag = 1;
509*8e28d849SEd Maste options.log_level = SYSLOG_LEVEL_DEBUG1;
510*8e28d849SEd Maste } else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
511*8e28d849SEd Maste options.log_level++;
512*8e28d849SEd Maste break;
513*8e28d849SEd Maste case 'D':
514*8e28d849SEd Maste /* ignore */
515*8e28d849SEd Maste break;
516*8e28d849SEd Maste case 'E':
517*8e28d849SEd Maste logfile = optarg;
518*8e28d849SEd Maste /* FALLTHROUGH */
519*8e28d849SEd Maste case 'e':
520*8e28d849SEd Maste /* ignore */
521*8e28d849SEd Maste break;
522*8e28d849SEd Maste case 'i':
523*8e28d849SEd Maste inetd_flag = 1;
524*8e28d849SEd Maste break;
525*8e28d849SEd Maste case 'r':
526*8e28d849SEd Maste /* ignore */
527*8e28d849SEd Maste break;
528*8e28d849SEd Maste case 'R':
529*8e28d849SEd Maste rexeced_flag = 1;
530*8e28d849SEd Maste break;
531*8e28d849SEd Maste case 'Q':
532*8e28d849SEd Maste /* ignored */
533*8e28d849SEd Maste break;
534*8e28d849SEd Maste case 'q':
535*8e28d849SEd Maste options.log_level = SYSLOG_LEVEL_QUIET;
536*8e28d849SEd Maste break;
537*8e28d849SEd Maste case 'b':
538*8e28d849SEd Maste /* protocol 1, ignored */
539*8e28d849SEd Maste break;
540*8e28d849SEd Maste case 'p':
541*8e28d849SEd Maste options.ports_from_cmdline = 1;
542*8e28d849SEd Maste if (options.num_ports >= MAX_PORTS) {
543*8e28d849SEd Maste fprintf(stderr, "too many ports.\n");
544*8e28d849SEd Maste exit(1);
545*8e28d849SEd Maste }
546*8e28d849SEd Maste options.ports[options.num_ports++] = a2port(optarg);
547*8e28d849SEd Maste if (options.ports[options.num_ports-1] <= 0) {
548*8e28d849SEd Maste fprintf(stderr, "Bad port number.\n");
549*8e28d849SEd Maste exit(1);
550*8e28d849SEd Maste }
551*8e28d849SEd Maste break;
552*8e28d849SEd Maste case 'g':
553*8e28d849SEd Maste if ((options.login_grace_time = convtime(optarg)) == -1) {
554*8e28d849SEd Maste fprintf(stderr, "Invalid login grace time.\n");
555*8e28d849SEd Maste exit(1);
556*8e28d849SEd Maste }
557*8e28d849SEd Maste break;
558*8e28d849SEd Maste case 'k':
559*8e28d849SEd Maste /* protocol 1, ignored */
560*8e28d849SEd Maste break;
561*8e28d849SEd Maste case 'h':
562*8e28d849SEd Maste servconf_add_hostkey("[command-line]", 0,
563*8e28d849SEd Maste &options, optarg, 1);
564*8e28d849SEd Maste break;
565*8e28d849SEd Maste case 't':
566*8e28d849SEd Maste case 'T':
567*8e28d849SEd Maste case 'G':
568*8e28d849SEd Maste fatal("test/dump modes not supported");
569*8e28d849SEd Maste break;
570*8e28d849SEd Maste case 'C':
571*8e28d849SEd Maste connection_info = server_get_connection_info(ssh, 0, 0);
572*8e28d849SEd Maste if (parse_server_match_testspec(connection_info,
573*8e28d849SEd Maste optarg) == -1)
574*8e28d849SEd Maste exit(1);
575*8e28d849SEd Maste break;
576*8e28d849SEd Maste case 'u':
577*8e28d849SEd Maste utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL);
578*8e28d849SEd Maste if (utmp_len > HOST_NAME_MAX+1) {
579*8e28d849SEd Maste fprintf(stderr, "Invalid utmp length.\n");
580*8e28d849SEd Maste exit(1);
581*8e28d849SEd Maste }
582*8e28d849SEd Maste break;
583*8e28d849SEd Maste case 'o':
584*8e28d849SEd Maste line = xstrdup(optarg);
585*8e28d849SEd Maste if (process_server_config_line(&options, line,
586*8e28d849SEd Maste "command-line", 0, NULL, NULL, &includes) != 0)
587*8e28d849SEd Maste exit(1);
588*8e28d849SEd Maste free(line);
589*8e28d849SEd Maste break;
590*8e28d849SEd Maste case 'V':
591*8e28d849SEd Maste fprintf(stderr, "%s, %s\n",
592*8e28d849SEd Maste SSH_VERSION, SSH_OPENSSL_VERSION);
593*8e28d849SEd Maste exit(0);
594*8e28d849SEd Maste default:
595*8e28d849SEd Maste usage();
596*8e28d849SEd Maste break;
597*8e28d849SEd Maste }
598*8e28d849SEd Maste }
599*8e28d849SEd Maste
600*8e28d849SEd Maste if (!rexeced_flag)
601*8e28d849SEd Maste fatal("sshd-auth should not be executed directly");
602*8e28d849SEd Maste
603*8e28d849SEd Maste #ifdef WITH_OPENSSL
604*8e28d849SEd Maste OpenSSL_add_all_algorithms();
605*8e28d849SEd Maste #endif
606*8e28d849SEd Maste
607*8e28d849SEd Maste /* If requested, redirect the logs to the specified logfile. */
608*8e28d849SEd Maste if (logfile != NULL) {
609*8e28d849SEd Maste char *cp, pid_s[32];
610*8e28d849SEd Maste
611*8e28d849SEd Maste snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid());
612*8e28d849SEd Maste cp = percent_expand(logfile,
613*8e28d849SEd Maste "p", pid_s,
614*8e28d849SEd Maste "P", "sshd-auth",
615*8e28d849SEd Maste (char *)NULL);
616*8e28d849SEd Maste log_redirect_stderr_to(cp);
617*8e28d849SEd Maste free(cp);
618*8e28d849SEd Maste }
619*8e28d849SEd Maste
620*8e28d849SEd Maste log_init(__progname,
621*8e28d849SEd Maste options.log_level == SYSLOG_LEVEL_NOT_SET ?
622*8e28d849SEd Maste SYSLOG_LEVEL_INFO : options.log_level,
623*8e28d849SEd Maste options.log_facility == SYSLOG_FACILITY_NOT_SET ?
624*8e28d849SEd Maste SYSLOG_FACILITY_AUTH : options.log_facility, 1);
625*8e28d849SEd Maste
626*8e28d849SEd Maste /* XXX can't use monitor_init(); it makes fds */
627*8e28d849SEd Maste pmonitor = xcalloc(1, sizeof(*pmonitor));
628*8e28d849SEd Maste pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
629*8e28d849SEd Maste pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
630*8e28d849SEd Maste pmonitor->m_log_sendfd = PRIVSEP_LOG_FD;
631*8e28d849SEd Maste set_log_handler(mm_log_handler, pmonitor);
632*8e28d849SEd Maste
633*8e28d849SEd Maste /* Check that there are no remaining arguments. */
634*8e28d849SEd Maste if (optind < ac) {
635*8e28d849SEd Maste fprintf(stderr, "Extra argument %s.\n", av[optind]);
636*8e28d849SEd Maste exit(1);
637*8e28d849SEd Maste }
638*8e28d849SEd Maste
639*8e28d849SEd Maste /* Connection passed by stdin/out */
640*8e28d849SEd Maste if (inetd_flag) {
641*8e28d849SEd Maste /*
642*8e28d849SEd Maste * NB. must be different fd numbers for the !socket case,
643*8e28d849SEd Maste * as packet_connection_is_on_socket() depends on this.
644*8e28d849SEd Maste */
645*8e28d849SEd Maste sock_in = dup(STDIN_FILENO);
646*8e28d849SEd Maste sock_out = dup(STDOUT_FILENO);
647*8e28d849SEd Maste } else {
648*8e28d849SEd Maste /* rexec case; accept()ed socket in ancestor listener */
649*8e28d849SEd Maste sock_in = sock_out = dup(STDIN_FILENO);
650*8e28d849SEd Maste }
651*8e28d849SEd Maste
652*8e28d849SEd Maste if (stdfd_devnull(1, 1, 0) == -1)
653*8e28d849SEd Maste error("stdfd_devnull failed");
654*8e28d849SEd Maste debug("network sockets: %d, %d", sock_in, sock_out);
655*8e28d849SEd Maste
656*8e28d849SEd Maste /*
657*8e28d849SEd Maste * Register our connection. This turns encryption off because we do
658*8e28d849SEd Maste * not have a key.
659*8e28d849SEd Maste */
660*8e28d849SEd Maste if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL)
661*8e28d849SEd Maste fatal("Unable to create connection");
662*8e28d849SEd Maste the_active_state = ssh;
663*8e28d849SEd Maste ssh_packet_set_server(ssh);
664*8e28d849SEd Maste pmonitor->m_pkex = &ssh->kex;
665*8e28d849SEd Maste
666*8e28d849SEd Maste /* Fetch our configuration */
667*8e28d849SEd Maste if ((cfg = sshbuf_new()) == NULL)
668*8e28d849SEd Maste fatal("sshbuf_new config buf failed");
669*8e28d849SEd Maste setproctitle("%s", "[session-auth early]");
670*8e28d849SEd Maste recv_privsep_state(ssh, cfg, &timing_secret);
671*8e28d849SEd Maste parse_server_config(&options, "rexec", cfg, &includes, NULL, 1);
672*8e28d849SEd Maste /* Fill in default values for those options not explicitly set. */
673*8e28d849SEd Maste fill_default_server_options(&options);
674*8e28d849SEd Maste options.timing_secret = timing_secret; /* XXX eliminate from unpriv */
675*8e28d849SEd Maste
676*8e28d849SEd Maste /* Reinit logging in case config set Level, Facility or Verbose. */
677*8e28d849SEd Maste log_init(__progname, options.log_level, options.log_facility, 1);
678*8e28d849SEd Maste
679*8e28d849SEd Maste debug("sshd-auth version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION);
680*8e28d849SEd Maste
681*8e28d849SEd Maste /* Store privilege separation user for later use if required. */
682*8e28d849SEd Maste privsep_chroot = (getuid() == 0 || geteuid() == 0);
683*8e28d849SEd Maste if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
684*8e28d849SEd Maste if (privsep_chroot || options.kerberos_authentication)
685*8e28d849SEd Maste fatal("Privilege separation user %s does not exist",
686*8e28d849SEd Maste SSH_PRIVSEP_USER);
687*8e28d849SEd Maste } else {
688*8e28d849SEd Maste privsep_pw = pwcopy(privsep_pw);
689*8e28d849SEd Maste freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd));
690*8e28d849SEd Maste privsep_pw->pw_passwd = xstrdup("*");
691*8e28d849SEd Maste }
692*8e28d849SEd Maste endpwent();
693*8e28d849SEd Maste
694*8e28d849SEd Maste #ifdef WITH_OPENSSL
695*8e28d849SEd Maste if (options.moduli_file != NULL)
696*8e28d849SEd Maste dh_set_moduli_file(options.moduli_file);
697*8e28d849SEd Maste #endif
698*8e28d849SEd Maste
699*8e28d849SEd Maste if (options.host_key_agent) {
700*8e28d849SEd Maste if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
701*8e28d849SEd Maste setenv(SSH_AUTHSOCKET_ENV_NAME,
702*8e28d849SEd Maste options.host_key_agent, 1);
703*8e28d849SEd Maste if ((r = ssh_get_authentication_socket(NULL)) == 0)
704*8e28d849SEd Maste have_agent = 1;
705*8e28d849SEd Maste else
706*8e28d849SEd Maste error_r(r, "Could not connect to agent \"%s\"",
707*8e28d849SEd Maste options.host_key_agent);
708*8e28d849SEd Maste }
709*8e28d849SEd Maste
710*8e28d849SEd Maste if (options.num_host_key_files != num_hostkeys) {
711*8e28d849SEd Maste fatal("internal error: hostkeys confused (config %u recvd %u)",
712*8e28d849SEd Maste options.num_host_key_files, num_hostkeys);
713*8e28d849SEd Maste }
714*8e28d849SEd Maste
715*8e28d849SEd Maste for (i = 0; i < options.num_host_key_files; i++) {
716*8e28d849SEd Maste if (host_pubkeys[i] != NULL) {
717*8e28d849SEd Maste have_key = 1;
718*8e28d849SEd Maste break;
719*8e28d849SEd Maste }
720*8e28d849SEd Maste }
721*8e28d849SEd Maste if (!have_key)
722*8e28d849SEd Maste fatal("internal error: received no hostkeys");
723*8e28d849SEd Maste
724*8e28d849SEd Maste /* Ensure that umask disallows at least group and world write */
725*8e28d849SEd Maste new_umask = umask(0077) | 0022;
726*8e28d849SEd Maste (void) umask(new_umask);
727*8e28d849SEd Maste
728*8e28d849SEd Maste /* Initialize the log (it is reinitialized below in case we forked). */
729*8e28d849SEd Maste log_init(__progname, options.log_level, options.log_facility, 1);
730*8e28d849SEd Maste set_log_handler(mm_log_handler, pmonitor);
731*8e28d849SEd Maste for (i = 0; i < options.num_log_verbose; i++)
732*8e28d849SEd Maste log_verbose_add(options.log_verbose[i]);
733*8e28d849SEd Maste
734*8e28d849SEd Maste /*
735*8e28d849SEd Maste * Chdir to the root directory so that the current disk can be
736*8e28d849SEd Maste * unmounted if desired.
737*8e28d849SEd Maste */
738*8e28d849SEd Maste if (chdir("/") == -1)
739*8e28d849SEd Maste error("chdir(\"/\"): %s", strerror(errno));
740*8e28d849SEd Maste
741*8e28d849SEd Maste /* This is the child authenticating a new connection. */
742*8e28d849SEd Maste setproctitle("%s", "[session-auth]");
743*8e28d849SEd Maste
744*8e28d849SEd Maste /* Executed child processes don't need these. */
745*8e28d849SEd Maste fcntl(sock_out, F_SETFD, FD_CLOEXEC);
746*8e28d849SEd Maste fcntl(sock_in, F_SETFD, FD_CLOEXEC);
747*8e28d849SEd Maste
748*8e28d849SEd Maste ssh_signal(SIGPIPE, SIG_IGN);
749*8e28d849SEd Maste ssh_signal(SIGALRM, SIG_DFL);
750*8e28d849SEd Maste ssh_signal(SIGHUP, SIG_DFL);
751*8e28d849SEd Maste ssh_signal(SIGTERM, SIG_DFL);
752*8e28d849SEd Maste ssh_signal(SIGQUIT, SIG_DFL);
753*8e28d849SEd Maste ssh_signal(SIGCHLD, SIG_DFL);
754*8e28d849SEd Maste
755*8e28d849SEd Maste /* Prepare the channels layer */
756*8e28d849SEd Maste channel_init_channels(ssh);
757*8e28d849SEd Maste channel_set_af(ssh, options.address_family);
758*8e28d849SEd Maste server_process_channel_timeouts(ssh);
759*8e28d849SEd Maste server_process_permitopen(ssh);
760*8e28d849SEd Maste
761*8e28d849SEd Maste ssh_packet_set_nonblocking(ssh);
762*8e28d849SEd Maste
763*8e28d849SEd Maste /* allocate authentication context */
764*8e28d849SEd Maste authctxt = xcalloc(1, sizeof(*authctxt));
765*8e28d849SEd Maste ssh->authctxt = authctxt;
766*8e28d849SEd Maste
767*8e28d849SEd Maste /* XXX global for cleanup, access from other modules */
768*8e28d849SEd Maste the_authctxt = authctxt;
769*8e28d849SEd Maste
770*8e28d849SEd Maste /* Set default key authentication options */
771*8e28d849SEd Maste if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL)
772*8e28d849SEd Maste fatal("allocation failed");
773*8e28d849SEd Maste
774*8e28d849SEd Maste /* prepare buffer to collect messages to display to user after login */
775*8e28d849SEd Maste if ((loginmsg = sshbuf_new()) == NULL)
776*8e28d849SEd Maste fatal("sshbuf_new loginmsg failed");
777*8e28d849SEd Maste auth_debug_reset();
778*8e28d849SEd Maste
779*8e28d849SEd Maste /* Enable challenge-response authentication for privilege separation */
780*8e28d849SEd Maste privsep_challenge_enable();
781*8e28d849SEd Maste
782*8e28d849SEd Maste #ifdef GSSAPI
783*8e28d849SEd Maste /* Cache supported mechanism OIDs for later use */
784*8e28d849SEd Maste ssh_gssapi_prepare_supported_oids();
785*8e28d849SEd Maste #endif
786*8e28d849SEd Maste
787*8e28d849SEd Maste privsep_child_demote();
788*8e28d849SEd Maste
789*8e28d849SEd Maste /* perform the key exchange */
790*8e28d849SEd Maste /* authenticate user and start session */
791*8e28d849SEd Maste do_ssh2_kex(ssh);
792*8e28d849SEd Maste do_authentication2(ssh);
793*8e28d849SEd Maste
794*8e28d849SEd Maste /*
795*8e28d849SEd Maste * The unprivileged child now transfers the current keystate and exits.
796*8e28d849SEd Maste */
797*8e28d849SEd Maste mm_send_keystate(ssh, pmonitor);
798*8e28d849SEd Maste ssh_packet_clear_keys(ssh);
799*8e28d849SEd Maste exit(0);
800*8e28d849SEd Maste }
801*8e28d849SEd Maste
802*8e28d849SEd Maste int
sshd_hostkey_sign(struct ssh * ssh,struct sshkey * privkey,struct sshkey * pubkey,u_char ** signature,size_t * slenp,const u_char * data,size_t dlen,const char * alg)803*8e28d849SEd Maste sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
804*8e28d849SEd Maste struct sshkey *pubkey, u_char **signature, size_t *slenp,
805*8e28d849SEd Maste const u_char *data, size_t dlen, const char *alg)
806*8e28d849SEd Maste {
807*8e28d849SEd Maste if (privkey) {
808*8e28d849SEd Maste if (mm_sshkey_sign(ssh, privkey, signature, slenp,
809*8e28d849SEd Maste data, dlen, alg, options.sk_provider, NULL,
810*8e28d849SEd Maste ssh->compat) < 0)
811*8e28d849SEd Maste fatal_f("privkey sign failed");
812*8e28d849SEd Maste } else {
813*8e28d849SEd Maste if (mm_sshkey_sign(ssh, pubkey, signature, slenp,
814*8e28d849SEd Maste data, dlen, alg, options.sk_provider, NULL,
815*8e28d849SEd Maste ssh->compat) < 0)
816*8e28d849SEd Maste fatal_f("pubkey sign failed");
817*8e28d849SEd Maste }
818*8e28d849SEd Maste return 0;
819*8e28d849SEd Maste }
820*8e28d849SEd Maste
821*8e28d849SEd Maste /* SSH2 key exchange */
822*8e28d849SEd Maste static void
do_ssh2_kex(struct ssh * ssh)823*8e28d849SEd Maste do_ssh2_kex(struct ssh *ssh)
824*8e28d849SEd Maste {
825*8e28d849SEd Maste char *hkalgs = NULL, *myproposal[PROPOSAL_MAX];
826*8e28d849SEd Maste const char *compression = NULL;
827*8e28d849SEd Maste struct kex *kex;
828*8e28d849SEd Maste int r;
829*8e28d849SEd Maste
830*8e28d849SEd Maste if (options.rekey_limit || options.rekey_interval)
831*8e28d849SEd Maste ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
832*8e28d849SEd Maste options.rekey_interval);
833*8e28d849SEd Maste
834*8e28d849SEd Maste if (options.compression == COMP_NONE)
835*8e28d849SEd Maste compression = "none";
836*8e28d849SEd Maste hkalgs = list_hostkey_types();
837*8e28d849SEd Maste
838*8e28d849SEd Maste kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms,
839*8e28d849SEd Maste options.ciphers, options.macs, compression, hkalgs);
840*8e28d849SEd Maste
841*8e28d849SEd Maste free(hkalgs);
842*8e28d849SEd Maste
843*8e28d849SEd Maste /* start key exchange */
844*8e28d849SEd Maste if ((r = kex_setup(ssh, myproposal)) != 0)
845*8e28d849SEd Maste fatal_r(r, "kex_setup");
846*8e28d849SEd Maste kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
847*8e28d849SEd Maste kex = ssh->kex;
848*8e28d849SEd Maste
849*8e28d849SEd Maste #ifdef WITH_OPENSSL
850*8e28d849SEd Maste kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
851*8e28d849SEd Maste kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
852*8e28d849SEd Maste kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
853*8e28d849SEd Maste kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
854*8e28d849SEd Maste kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
855*8e28d849SEd Maste kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
856*8e28d849SEd Maste kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
857*8e28d849SEd Maste # ifdef OPENSSL_HAS_ECC
858*8e28d849SEd Maste kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
859*8e28d849SEd Maste # endif /* OPENSSL_HAS_ECC */
860*8e28d849SEd Maste #endif /* WITH_OPENSSL */
861*8e28d849SEd Maste kex->kex[KEX_C25519_SHA256] = kex_gen_server;
862*8e28d849SEd Maste kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
863*8e28d849SEd Maste kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server;
864*8e28d849SEd Maste kex->load_host_public_key=&get_hostkey_public_by_type;
865*8e28d849SEd Maste kex->load_host_private_key=&get_hostkey_private_by_type;
866*8e28d849SEd Maste kex->host_key_index=&get_hostkey_index;
867*8e28d849SEd Maste kex->sign = sshd_hostkey_sign;
868*8e28d849SEd Maste
869*8e28d849SEd Maste ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done);
870*8e28d849SEd Maste kex_proposal_free_entries(myproposal);
871*8e28d849SEd Maste
872*8e28d849SEd Maste #ifdef DEBUG_KEXDH
873*8e28d849SEd Maste /* send 1st encrypted/maced/compressed message */
874*8e28d849SEd Maste if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
875*8e28d849SEd Maste (r = sshpkt_put_cstring(ssh, "markus")) != 0 ||
876*8e28d849SEd Maste (r = sshpkt_send(ssh)) != 0 ||
877*8e28d849SEd Maste (r = ssh_packet_write_wait(ssh)) != 0)
878*8e28d849SEd Maste fatal_fr(r, "send test");
879*8e28d849SEd Maste #endif
880*8e28d849SEd Maste debug("KEX done");
881*8e28d849SEd Maste }
882*8e28d849SEd Maste
883*8e28d849SEd Maste /* server specific fatal cleanup */
884*8e28d849SEd Maste void
cleanup_exit(int i)885*8e28d849SEd Maste cleanup_exit(int i)
886*8e28d849SEd Maste {
887*8e28d849SEd Maste _exit(i);
888*8e28d849SEd Maste }
889