server.c 4.05 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
2
/* server.c
 *
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Möller
 *
 * 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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 */

#include "server.h"

#include "version.h"
#include "connection.h"
#include "abstract_io.h"
#include "read_line.h"
#include "read_packet.h"
#include "debug.h"
#include "format.h"
#include "werror.h"
#include "void.h"
#include "xalloc.h"

struct read_handler *make_server_read_line();
struct callback *make_server_close_handler();

Niels Möller's avatar
Niels Möller committed
42
static int server_initiate(struct fd_callback **c,
Niels Möller's avatar
Niels Möller committed
43
44
			   int fd)
{
Niels Möller's avatar
Niels Möller committed
45
46
  struct server_callback *closure = (struct server_callback *) *c;
  
Niels Möller's avatar
Niels Möller committed
47
48
  /* FIXME: Should pass a key exchange handler, not NULL! */
  struct ssh_connection *connection = make_ssh_connection(NULL);
Niels Möller's avatar
Niels Möller committed
49
50
51
52
53
54
55
  struct abstract_write *write =
    io_read_write(closure->backend, fd,
		  make_server_read_line(),
		  closure->block_size,
		  make_server_close_handler());
  
  connection->server_version
Niels Möller's avatar
Niels Möller committed
56
    = ssh_format("SSH-%lz-%lz %lz",
Niels Möller's avatar
Niels Möller committed
57
58
59
		 PROTOCOL_VERSION,
		 SOFTWARE_SERVER_VERSION,
		 closure->id_comment);
Niels Möller's avatar
Niels Möller committed
60
61

  return A_WRITE(write, ssh_format("%lS\r\n", connection->server_version));
Niels Möller's avatar
Niels Möller committed
62
63
64
65
66
67
68
69
}

struct server_line_handler
{
  struct line_handler super;
  struct ssh_connection *connection;
};

Niels Möller's avatar
Niels Möller committed
70
static struct read_handler *do_line(struct line_handler **h,
Niels Möller's avatar
Niels Möller committed
71
72
73
				    UINT32 length,
				    UINT8 *line)
{
Niels Möller's avatar
Niels Möller committed
74
75
  struct server_line_handler *closure = (struct server_line_handler *) *h;
  
Niels Möller's avatar
Niels Möller committed
76
77
78
79
80
81
  if ( (length >= 4) && !memcmp(line, "SSH-", 4))
    {
      /* Parse and remember format string */
      if ((length >= 8) && !memcmp(line + 4, "2.0-", 4))
	{
	  struct read_handler *new
Niels Möller's avatar
Niels Möller committed
82
	    = make_read_packet(make_packet_debug(&closure->connection->super,
Niels Möller's avatar
Niels Möller committed
83
						 stderr),
84
			       closure->connection);
Niels Möller's avatar
Niels Möller committed
85
86
	  
	  closure->connection->client_version
Niels Möller's avatar
Niels Möller committed
87
	    = ssh_format("%ls", length, line);
Niels Möller's avatar
Niels Möller committed
88

Niels Möller's avatar
Niels Möller committed
89
90
91
92
93
	  verbose("Client version: ");
	  verbose_safe(closure->connection->client_version->length,
		       closure->connection->client_version->data);
	  verbose("\n");
	  
Niels Möller's avatar
Niels Möller committed
94
	  /* FIXME: Cleanup properly. */
Niels Möller's avatar
Niels Möller committed
95
	  lsh_free(closure);
Niels Möller's avatar
Niels Möller committed
96
97
98
99
100
101
102
103
104

	  return new;
	}
      else
	{
	  werror("Unsupported protocol version: ");
	  werror_safe(length, line);
	  werror("\n");

Niels Möller's avatar
Niels Möller committed
105
106
107
108
	  /* FIXME: Clean up properly */
	  lsh_free(closure);
	  *h = 0;
		  
Niels Möller's avatar
Niels Möller committed
109
110
111
112
113
114
115
116
117
118
119
120
	  return 0;
	}
    }
  else
    {
      /* Display line */
      werror_safe(length, line);

      /* Read next line */
      return 0;
    }
}
Niels Möller's avatar
Niels Möller committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134

struct read_handler *make_server_read_line(struct ssh_connection *s)
{
  struct server_line_handler *closure
    = xalloc(sizeof(struct server_line_handler));
  
  closure->super.handler = do_line;
  closure->connection = s;
  
  return make_read_line(&closure->super);
}

struct fd_callback *make_server_callback(struct io_backend *b,
					 char *comment,
Niels Möller's avatar
Niels Möller committed
135
136
137
138
					 UINT32 block_size,
					 struct signer *secret,
					 struct lsh_string *host_key,
					 struct randomness *r)
Niels Möller's avatar
Niels Möller committed
139
140
141
142
143
144
145
146
					 
{
  struct server_callback *connected = xalloc(sizeof(struct server_callback));

  connected->super.f = server_initiate;
  connected->backend = b;
  connected->block_size = block_size;
  connected->id_comment = comment;
Niels Möller's avatar
Niels Möller committed
147
148
149
  connected->secret = secret;
  connected->host_key = host_key;
  connected->random = r;
Niels Möller's avatar
Niels Möller committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  
  return &connected->super;
}

static int server_die(struct callback *closure)
{
  werror("Connection died.\n");
  /* FIXME: Cleanup properly. */
  return 0;  /* Ignored */
}

struct callback *make_server_close_handler()
{
  struct callback *c = xalloc(sizeof(struct callback));

  c->f = server_die;

  return c;
}