~ubuntu-branches/ubuntu/quantal/libssh/quantal-updates

1 by Laurent Bigonville
Import upstream version 0.2
1
/*
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
2
 * session.c - non-networking functions
1 by Laurent Bigonville
Import upstream version 0.2
3
 *
4
 * This file is part of the SSH Library
5
 *
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
6
 * Copyright (c) 2005-2008 by Aris Adamantiadis
7
 *
1 by Laurent Bigonville
Import upstream version 0.2
8
 * The SSH Library is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or (at your
11
 * option) any later version.
12
 *
13
 * The SSH Library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16
 * License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with the SSH Library; see the file COPYING.  If not, write to
20
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
21
 * MA 02111-1307, USA.
22
 */
1 by Laurent Bigonville
Import upstream version 0.2
23
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
24
#include "config.h"
1 by Laurent Bigonville
Import upstream version 0.2
25
#include <string.h>
26
#include <stdlib.h>
27
#include "libssh/libssh.h"
28
#include "libssh/priv.h"
29
#include "libssh/server.h"
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
30
#include "libssh/socket.h"
31
#include "libssh/agent.h"
32
#include "libssh/packet.h"
33
#include "libssh/session.h"
34
#include "libssh/misc.h"
1.2.5 by Laurent Bigonville
Import upstream version 0.4.3
35
#include "libssh/ssh2.h"
36
#include "libssh/buffer.h"
1 by Laurent Bigonville
Import upstream version 0.2
37
#define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
38
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
39
/** \defgroup ssh_session SSH Session
1 by Laurent Bigonville
Import upstream version 0.2
40
 * \brief functions that manage a session
41
 */
42
/** \addtogroup ssh_session
43
 * @{ */
44
45
/** \brief creates a new ssh session
46
 * \returns new ssh_session pointer
47
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
48
ssh_session ssh_new(void) {
49
  ssh_session session;
1.2.4 by Laurent Bigonville
Import upstream version 0.4.2
50
  char *id;
51
  int rc;
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
52
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
53
  session = malloc(sizeof (struct ssh_session_struct));
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
54
  if (session == NULL) {
55
    return NULL;
56
  }
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
57
  ZERO_STRUCTP(session);
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
58
59
  session->next_crypto = crypto_new();
60
  if (session->next_crypto == NULL) {
61
    goto err;
62
  }
63
64
  session->socket = ssh_socket_new(session);
65
  if (session->socket == NULL) {
66
    goto err;
67
  }
68
69
  session->out_buffer = buffer_new();
70
  if (session->out_buffer == NULL) {
71
    goto err;
72
  }
73
74
  session->in_buffer=buffer_new();
75
  if (session->in_buffer == NULL) {
76
    goto err;
77
  }
78
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
79
  session->alive = 0;
80
  session->auth_methods = 0;
81
  session->blocking = 1;
82
  session->log_indent = 0;
83
  session->maxchannel = FIRST_CHANNEL;
84
85
  /* options */
86
  session->port = 22;
87
  session->fd = -1;
88
  session->ssh2 = 1;
89
#ifdef WITH_SSH1
90
  session->ssh1 = 1;
91
#else
92
  session->ssh1 = 0;
93
#endif
94
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
95
#ifndef _WIN32
96
    session->agent = agent_new(session);
97
    if (session->agent == NULL) {
98
      goto err;
99
    }
100
#endif /* _WIN32 */
1.2.4 by Laurent Bigonville
Import upstream version 0.4.2
101
102
    session->identity = ssh_list_new();
103
    if (session->identity == NULL) {
104
      goto err;
105
    }
106
1.2.6 by Laurent Bigonville
Import upstream version 0.4.4
107
    id = strdup("%d/id_rsa");
108
    if (id == NULL) {
109
      goto err;
110
    }
111
    rc = ssh_list_append(session->identity, id);
112
    if (rc == SSH_ERROR) {
113
      goto err;
114
    }
115
116
    id = strdup("%d/id_dsa");
117
    if (id == NULL) {
118
      goto err;
119
    }
120
    rc = ssh_list_append(session->identity, id);
121
    if (rc == SSH_ERROR) {
122
      goto err;
123
    }
124
125
    id = strdup("%d/identity");
1.2.4 by Laurent Bigonville
Import upstream version 0.4.2
126
    if (id == NULL) {
127
      goto err;
128
    }
129
    rc = ssh_list_append(session->identity, id);
130
    if (rc == SSH_ERROR) {
131
      goto err;
132
    }
133
1 by Laurent Bigonville
Import upstream version 0.2
134
    return session;
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
135
136
err:
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
137
    ssh_free(session);
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
138
    return NULL;
1 by Laurent Bigonville
Import upstream version 0.2
139
}
140
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
141
/**
142
 * @brief deallocate a session handle
143
 * @see ssh_disconnect()
144
 * @see ssh_new()
145
 */
146
void ssh_free(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
147
  int i;
148
  enter_function();
149
150
  if (session == NULL) {
151
    return;
152
  }
153
154
  SAFE_FREE(session->serverbanner);
155
  SAFE_FREE(session->clientbanner);
156
  SAFE_FREE(session->banner);
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
157
#ifdef WITH_PCAP
158
  if(session->pcap_ctx){
159
  	ssh_pcap_context_free(session->pcap_ctx);
160
  	session->pcap_ctx=NULL;
161
  }
162
#endif
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
163
  buffer_free(session->in_buffer);
164
  buffer_free(session->out_buffer);
165
  session->in_buffer=session->out_buffer=NULL;
166
  crypto_free(session->current_crypto);
167
  crypto_free(session->next_crypto);
168
  ssh_socket_free(session->socket);
169
  /* delete all channels */
170
  while (session->channels) {
171
    channel_free(session->channels);
172
  }
173
#ifndef _WIN32
174
  agent_free(session->agent);
175
#endif /* _WIN32 */
176
  if (session->client_kex.methods) {
177
    for (i = 0; i < 10; i++) {
178
      SAFE_FREE(session->client_kex.methods[i]);
179
    }
180
  }
181
182
  if (session->server_kex.methods) {
183
    for (i = 0; i < 10; i++) {
184
      SAFE_FREE(session->server_kex.methods[i]);
185
    }
186
  }
187
  SAFE_FREE(session->client_kex.methods);
188
  SAFE_FREE(session->server_kex.methods);
189
190
  privatekey_free(session->dsa_key);
191
  privatekey_free(session->rsa_key);
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
192
  if(session->ssh_message_list){
193
    ssh_message msg;
1.2.4 by Laurent Bigonville
Import upstream version 0.4.2
194
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
195
        != NULL){
196
      ssh_message_free(msg);
197
    }
198
    ssh_list_free(session->ssh_message_list);
199
  }
200
1.2.4 by Laurent Bigonville
Import upstream version 0.4.2
201
  if (session->identity) {
202
    char *id;
203
204
    for (id = ssh_list_pop_head(char *, session->identity);
205
         id != NULL;
206
         id = ssh_list_pop_head(char *, session->identity)) {
207
      SAFE_FREE(id);
208
    }
209
    ssh_list_free(session->identity);
210
  }
211
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
212
  /* options */
213
  SAFE_FREE(session->username);
214
  SAFE_FREE(session->host);
215
  SAFE_FREE(session->sshdir);
216
  SAFE_FREE(session->knownhosts);
1.2.5 by Laurent Bigonville
Import upstream version 0.4.3
217
  SAFE_FREE(session->ProxyCommand);
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
218
219
  for (i = 0; i < 10; i++) {
220
    if (session->wanted_methods[i]) {
221
      SAFE_FREE(session->wanted_methods[i]);
222
    }
223
  }
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
224
225
  /* burn connection, it could hang sensitive datas */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
226
  ZERO_STRUCTP(session);
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
227
  SAFE_FREE(session);
1 by Laurent Bigonville
Import upstream version 0.2
228
}
229
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
230
/** \brief disconnect impolitely from remote host by closing the socket.
231
 * Suitable if you forked and want to destroy this session.
1 by Laurent Bigonville
Import upstream version 0.2
232
 * \param session current ssh session
233
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
234
void ssh_silent_disconnect(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
235
  enter_function();
236
237
  if (session == NULL) {
238
    return;
239
  }
240
241
  ssh_socket_close(session->socket);
242
  session->alive = 0;
243
  ssh_disconnect(session);
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
244
  leave_function();
1 by Laurent Bigonville
Import upstream version 0.2
245
}
246
247
/** \brief set the session in blocking/nonblocking mode
248
 * \param session ssh session
249
 * \param blocking zero for nonblocking mode
250
 * \bug nonblocking code is in development and won't work as expected
251
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
252
void ssh_set_blocking(ssh_session session, int blocking) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
253
  if (session == NULL) {
254
    return;
255
  }
256
257
  session->blocking = blocking ? 1 : 0;
1 by Laurent Bigonville
Import upstream version 0.2
258
}
259
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
260
/** In case you'd need the file descriptor of the connection
261
 * to the server/client
1 by Laurent Bigonville
Import upstream version 0.2
262
 * \brief recover the fd of connection
263
 * \param session ssh session
264
 * \return file descriptor of the connection, or -1 if it is
265
 * not connected
266
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
267
socket_t ssh_get_fd(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
268
  if (session == NULL) {
269
    return -1;
270
  }
271
272
  return ssh_socket_get_fd(session->socket);
1 by Laurent Bigonville
Import upstream version 0.2
273
}
274
275
/** \brief say to the session it has data to read on the file descriptor without blocking
276
 * \param session ssh session
277
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
278
void ssh_set_fd_toread(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
279
  if (session == NULL) {
280
    return;
281
  }
282
283
  ssh_socket_set_toread(session->socket);
1 by Laurent Bigonville
Import upstream version 0.2
284
}
285
286
/** \brief say the session it may write to the file descriptor without blocking
287
 * \param session ssh session
288
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
289
void ssh_set_fd_towrite(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
290
  if (session == NULL) {
291
    return;
292
  }
293
294
  ssh_socket_set_towrite(session->socket);
1 by Laurent Bigonville
Import upstream version 0.2
295
}
296
297
/** \brief say the session it has an exception to catch on the file descriptor
298
 * \param session ssh session
299
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
300
void ssh_set_fd_except(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
301
  if (session == NULL) {
302
    return;
303
  }
304
305
  ssh_socket_set_except(session->socket);
1 by Laurent Bigonville
Import upstream version 0.2
306
}
307
308
/** \warning I don't remember if this should be internal or not
309
 */
310
/* looks if there is data to read on the socket and parse it. */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
311
int ssh_handle_packets(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
312
  int w = 0;
313
  int e = 0;
314
  int rc = -1;
315
316
  enter_function();
317
318
  do {
319
    rc = ssh_socket_poll(session->socket, &w, &e);
320
    if (rc <= 0) {
321
      /* error or no data available */
322
      leave_function();
323
      return rc;
324
    }
325
326
    /* if an exception happened, it will be trapped by packet_read() */
327
    if ((packet_read(session) != SSH_OK) ||
328
        (packet_translate(session) != SSH_OK)) {
329
      leave_function();
330
      return -1;
331
    }
332
333
    packet_parse(session);
334
  } while(rc > 0);
335
336
  leave_function();
337
  return rc;
1 by Laurent Bigonville
Import upstream version 0.2
338
}
339
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
340
/**
341
 * @brief Get session status
342
 *
343
 * @param session       The ssh session to use.
344
 *
345
 * @returns A bitmask including SSH_CLOSED, SSH_READ_PENDING or SSH_CLOSED_ERROR
346
 *          which respectively means the session is closed, has data to read on
347
 *          the connection socket and session was closed due to an error.
1 by Laurent Bigonville
Import upstream version 0.2
348
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
349
int ssh_get_status(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
350
  int socketstate;
351
  int r = 0;
352
353
  if (session == NULL) {
354
    return 0;
355
  }
356
357
  socketstate = ssh_socket_get_status(session->socket);
358
359
  if (session->closed) {
360
    r |= SSH_CLOSED;
361
  }
362
  if (socketstate & SSH_READ_PENDING) {
363
    r |= SSH_READ_PENDING;
364
  }
365
  if (session->closed && (socketstate & SSH_CLOSED_ERROR)) {
366
    r |= SSH_CLOSED_ERROR;
367
  }
368
369
  return r;
1 by Laurent Bigonville
Import upstream version 0.2
370
}
371
372
/** \brief get the disconnect message from the server
373
 * \param session ssh session
374
 * \return message sent by the server along with the disconnect, or NULL in which case the reason of the disconnect may be found with ssh_get_error.
375
 * \see ssh_get_error()
376
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
377
const char *ssh_get_disconnect_message(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
378
  if (session == NULL) {
1 by Laurent Bigonville
Import upstream version 0.2
379
    return NULL;
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
380
  }
381
382
  if (!session->closed) {
383
    ssh_set_error(session, SSH_REQUEST_DENIED,
384
        "Connection not closed yet");
385
  } else if(session->closed_by_except) {
386
    ssh_set_error(session, SSH_REQUEST_DENIED,
387
        "Connection closed by socket error");
388
  } else if(!session->discon_msg) {
389
    ssh_set_error(session, SSH_FATAL,
390
        "Connection correctly closed but no disconnect message");
391
  } else {
392
    return session->discon_msg;
393
  }
394
395
  return NULL;
1 by Laurent Bigonville
Import upstream version 0.2
396
}
397
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
398
/**
399
 * @brief Get the protocol version of the session.
400
 *
401
 * @param session       The ssh session to use.
402
 *
403
 * @return 1 or 2, for ssh1 or ssh2, < 0 on error.
1 by Laurent Bigonville
Import upstream version 0.2
404
 */
1.1.3 by Jonathan Thomas
Import upstream version 0.3.92
405
int ssh_get_version(ssh_session session) {
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
406
  if (session == NULL) {
407
    return -1;
408
  }
409
410
  return session->version;
1 by Laurent Bigonville
Import upstream version 0.2
411
}
412
1.2.5 by Laurent Bigonville
Import upstream version 0.4.3
413
414
/**
415
 * @internal
416
 * @handle a SSH_MSG_GLOBAL_REQUEST packet
417
 * @param session the SSH session
418
 */
419
void ssh_global_request_handle(ssh_session session){
420
  ssh_string type;
421
  char *type_c;
422
  uint32_t needreply;
423
  type=buffer_get_ssh_string(session->in_buffer);
424
  buffer_get_u32(session->in_buffer,&needreply);
425
  if(type==NULL)
426
    return;
427
  type_c=string_to_char(type);
428
  if(!type_c)
429
    return;
430
  ssh_log(session, SSH_LOG_PROTOCOL,
431
      "Received SSH_GLOBAL_REQUEST %s (wantreply=%d)",type_c,needreply);
432
  SAFE_FREE(type_c);
433
  string_free(type);
434
  if(needreply != 0){
435
    buffer_add_u8(session->out_buffer,SSH2_MSG_REQUEST_FAILURE);
436
    packet_send(session);
437
  }
438
}
439
1 by Laurent Bigonville
Import upstream version 0.2
440
/** @} */
1.1.2 by Jonathan Riddell
Import upstream version 0.3.4
441
/* vim: set ts=2 sw=2 et cindent: */