lshd.c 7.25 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1 2 3
/* lshd.c
 *
 * main server program.
4 5
 *
 * $Id$ */
Niels Möller's avatar
Niels Möller committed
6

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
Niels Möller's avatar
Niels Möller committed
25 26

#include <errno.h>
Niels Möller's avatar
Niels Möller committed
27
#include <locale.h>
Niels Möller's avatar
Niels Möller committed
28 29
#include <stdio.h>
#include <string.h>
Niels Möller's avatar
Niels Möller committed
30 31

#include "getopt.h"
Niels Möller's avatar
Niels Möller committed
32

33
#include "algorithms.h"
34 35
#include "alist.h"
#include "atoms.h"
36
#include "channel.h"
37
#include "charset.h"
38 39
#include "crypto.h"
#include "format.h"
Niels Möller's avatar
Niels Möller committed
40
#include "io.h"
Niels Möller's avatar
Niels Möller committed
41
#include "password.h"
42
#include "randomness.h"
Niels Möller's avatar
Niels Möller committed
43
#include "reaper.h"
Niels Möller's avatar
Niels Möller committed
44
#include "server.h"
45
#include "server_keyexchange.h"
Niels Möller's avatar
Niels Möller committed
46
#include "ssh.h"
Niels Möller's avatar
Niels Möller committed
47
#include "userauth.h"
48 49
#include "werror.h"
#include "xalloc.h"
Niels Möller's avatar
Niels Möller committed
50
#include "compress.h"
51

52
/* Block size for stdout and stderr buffers */
Niels Möller's avatar
Niels Möller committed
53 54
#define BLOCK_SIZE 32768

Niels Möller's avatar
Niels Möller committed
55
void usage(void) NORETURN;
Niels Möller's avatar
Niels Möller committed
56

Niels Möller's avatar
Niels Möller committed
57
void usage(void)
Niels Möller's avatar
Niels Möller committed
58
{
59
  fprintf(stderr, "lshd [-p port] [-q] [-d] [-i] [-v]\n");
Niels Möller's avatar
Niels Möller committed
60 61 62
  exit(1);
}

Niels Möller's avatar
Niels Möller committed
63 64 65 66
struct signer *secret_key;
struct lsh_string *public_key;

/* A key generated by gnupg */
67
static void init_host_key(struct randomness *r)
Niels Möller's avatar
Niels Möller committed
68 69 70
{
  mpz_t p, q, g, y, a;
  mpz_t tmp;
71
  struct lsh_string *s;
Niels Möller's avatar
Niels Möller committed
72 73 74 75 76 77 78
  
  mpz_init_set_str(p,
		   "BC7797D55CF2449CA4B02396246AF5C75CA38C52B6F2E543"
		   "6754198B137B25B0A81DFE269D5CDFD0AEA290A32BA5B918"
		   "B58D64762D40EAA8D70F282B3AC4A7771171B1B1D1AE89F4"
		   "1CD091FE95A6F42A2340081F9E97A4B5F953DE223F10F878"
		   "4C0619A9979643E5325DF71C9C088F3BC82FA0A6C47B5C64"
79
		   "BC07A31B9CDB2B07", 16);
Niels Möller's avatar
Niels Möller committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  mpz_init_set_str(q,
		   "867F7E6563B3FAF19B65C83E9B843150C5CC2201", 16);
  mpz_init_set_str(g,
		   "7FA83EAEDFD8679A4A80C869AD7E353F3B517569C2079C79"
		   "97EA6655764581B073F71AA15C07A789AEB213B106741AAB"
		   "CA81B8300B1F8510D3CD1C3D9D7D11640C1608E8E2E71527"
		   "68B8FDCB5544E29A020D14CC5C12E264C59E57E9F6832DA7"
		   "10B805CD9866C1110D60069D31D5A72D1A1ED96F2B11CFEF"
		   "7AB347F0632CB0C7", 16);
  mpz_init_set_str(y,
		   "2DA5B458DF3616097FA22DB6BDDD31A29E532054D4C208F7"
		   "EBF63EB2476E8E98E0885CFBC5669B56EC834E42058E8BCF"
		   "C259CA1BE981D7721306709499DE27E7B13F62359D9520D1"
		   "3D73C62E8E5C5F6B8E2C70217EC3B557FBCB98535BE3C6EE"
		   "0C71DEC1FE9C6791D3780DD8D593D5030969D303A5818B01"
		   "C4B855C07E8C4F64", 16);
96 97
  mpz_init_set_str(a,
		   "295190AEDBBD6EBD2F817F7D8CCC8B0095DCD82E", 16);
Niels Möller's avatar
Niels Möller committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

  mpz_init_set(tmp, g);
  mpz_powm(tmp, tmp, a, p);
  if (mpz_cmp(tmp, y))
    fatal("Test key invalid\n");

  mpz_clear(tmp);

  public_key = ssh_format("%a%n%n%n%n", ATOM_SSH_DSS, p, q, g, y);
  s = ssh_format("%n", a);

  secret_key = MAKE_SIGNER(make_dss_algorithm(r),
			   public_key->length, public_key->data,
			   s->length, s->data);

Niels Möller's avatar
Niels Möller committed
113 114 115
  if (!secret_key)
    fatal("Can't parse secret key\n");

116
  lsh_string_free(s);
Niels Möller's avatar
Niels Möller committed
117 118 119 120 121 122 123
  mpz_clear(p);
  mpz_clear(q);
  mpz_clear(g);
  mpz_clear(y);
  mpz_clear(a);
}

Niels Möller's avatar
Niels Möller committed
124 125
int main(int argc, char **argv)
{
126
  char *host = NULL;  /* Interface to bind */
Niels Möller's avatar
Niels Möller committed
127 128 129
  char *port = "ssh";
  int option;

130 131 132
  int preferred_crypto = 0;
  int preferred_compression = 0;
  int preferred_mac = 0;
133

134
  struct sockaddr_in local;
135

Niels Möller's avatar
Niels Möller committed
136 137
  struct reap *reaper;
  
138 139 140 141
  struct randomness *r;
  struct diffie_hellman_method *dh;
  struct keyexchange_algorithm *kex;
  struct alist *algorithms;
Niels Möller's avatar
Niels Möller committed
142
  struct make_kexinit *make_kexinit;
143
  struct packet_handler *kexinit_handler;
144 145 146 147

  NEW(io_backend, backend);
  gc_register_global(&backend->super);

Niels Möller's avatar
Niels Möller committed
148 149 150
  /* For filtering messages. Could perhaps also be used when converting
   * strings to and from UTF8. */
  setlocale(LC_CTYPE, "");
151 152
  /* FIXME: Choose character set depending on the locale */
  set_local_charset(CHARSET_LATIN1);
153 154 155

  r = make_reasonably_random();
  dh = make_dh1(r);
Niels Möller's avatar
Niels Möller committed
156
  
157 158 159 160 161 162 163
  algorithms = many_algorithms(1,
			       ATOM_SSH_DSS, make_dss_algorithm(r),
			       -1);

  while(1)
    {
      static struct option options[] =
Niels Möller's avatar
Niels Möller committed
164
      {
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
	{ "verbose", no_argument, NULL, 'v' },
	{ "quiet", no_argument, NULL, 'q' },
	{ "debug", no_argument, &debug_flag, 1},
	{ "port", required_argument, NULL, 'p' },
	{ "crypto", required_argument, NULL, 'c' },
	{ "compression", optional_argument, NULL, 'z'},
	{ "mac", required_argument, NULL, 'm' },
	{ NULL }
      };
      
      option = getopt_long(argc, argv, "c:p:qvz::", options, NULL);
      switch(option)
	{
	case -1:
	  goto options_done;
	case 0:
	  break;
	case 'p':
	  port = optarg;
	  break;
	case 'q':
	  quiet_flag = 1;
	  break;
	case 'v':
	  verbose_flag = 1;
	  break;
	case 'c':
	  preferred_crypto = lookup_crypto(algorithms, optarg);
	  if (!preferred_crypto)
	    {
	      werror("lsh: Unknown crypto algorithm '%s'.\n", optarg);
	      exit(1);
	    }
	  break;
	case 'z':
	  if (!optarg)
	    optarg = "zlib";
	
	  preferred_compression = lookup_compression(algorithms, optarg);
	  if (!preferred_compression)
	    {
	      werror("lsh: Unknown compression algorithm '%s'.\n", optarg);
	      exit(1);
	    }
	  break;
	case 'm':
	  preferred_mac = lookup_mac(algorithms, optarg);
	  if (!preferred_mac)
	    {
	      werror("lsh: Unknown message authentication algorithm '%s'.\n",
		      optarg);
	      exit(1);
	    }
	    
	case '?':
	  usage();
	}
    }
 options_done:
Niels Möller's avatar
Niels Möller committed
224 225 226 227

  if ( (argc - optind) != 0)
    usage();

228 229 230 231 232 233
  if (!get_inaddr(&local, host, port, "tcp"))
    {
      fprintf(stderr, "No such host or service");
      exit(1);
    }

234
  init_backend(backend);
Niels Möller's avatar
Niels Möller committed
235
  reaper = make_reaper();
Niels Möller's avatar
Niels Möller committed
236

237 238
  init_host_key(r); /* Initializes public_key and secret_key */
  kex = make_dh_server(dh, public_key, secret_key);
Niels Möller's avatar
Niels Möller committed
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
  ALIST_SET(algorithms, ATOM_DIFFIE_HELLMAN_GROUP1_SHA1, kex);

  make_kexinit
    = make_simple_kexinit(r,
			  make_int_list(1, ATOM_DIFFIE_HELLMAN_GROUP1_SHA1, -1),
			  make_int_list(1, ATOM_SSH_DSS, -1),
			  (preferred_crypto
			   ? make_int_list(1, preferred_crypto, -1)
			   : default_crypto_algorithms()),
			  (preferred_mac
			   ? make_int_list(1, preferred_mac, -1)
			   : default_mac_algorithms()),
			  (preferred_compression
			   ? make_int_list(1, preferred_compression, -1)
			   : default_compression_algorithms()),
			  make_int_list(0, -1));
256 257 258 259

  kexinit_handler = make_kexinit_handler
    (CONNECTION_SERVER,
     make_kexinit, algorithms,
Niels Möller's avatar
Niels Möller committed
260 261 262 263
     make_meta_service
     (make_alist
      (1, ATOM_SSH_USERAUTH,
       make_userauth_service
264
       (make_int_list(1, ATOM_PASSWORD, -1),
265
	make_alist(1, ATOM_PASSWORD,
Niels Möller's avatar
Niels Möller committed
266 267 268 269 270 271
		   make_unix_userauth
		   (make_alist(1,
			       ATOM_SSH_CONNECTION,
			       make_server_session_service
			       (make_alist(0, -1),
				make_alist(1, ATOM_SHELL,
272
					   make_shell_handler(backend,
Niels Möller's avatar
Niels Möller committed
273
							      reaper),
274 275 276 277
					   -1)),
			       -1)),
		   -1)),
       -1)));
Niels Möller's avatar
Niels Möller committed
278
     
279 280
  if (!io_listen(backend, &local, 
	    make_server_callback(backend,
281
				 "lsh - a free ssh",
282
				 SSH_MAX_PACKET,
Niels Möller's avatar
Niels Möller committed
283
				 r, make_kexinit,
284
				 kexinit_handler)))
Niels Möller's avatar
Niels Möller committed
285 286 287 288
    {
      werror("lsh: Connection failed: %s\n", strerror(errno));
      return 1;
    }
Niels Möller's avatar
Niels Möller committed
289
  
290
  reaper_run(reaper, backend);
Niels Möller's avatar
Niels Möller committed
291 292 293

  return 0;
}