1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
/*
* ProFTPD - mod_sftp services
* Copyright (c) 2008-2011 TJ Saunders
*
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*
* $Id: service.c,v 1.6 2011/05/23 21:03:12 castaglia Exp $
*/
#include "mod_sftp.h"
#include "ssh2.h"
#include "service.h"
#include "msg.h"
#include "packet.h"
#include "disconnect.h"
static pool *service_pool = NULL;
static const char *trace_channel = "ssh2";
static int read_service_req(struct ssh2_packet *pkt, char **service) {
char *buf, *service_name;
uint32_t buflen;
cmd_rec *cmd;
buf = pkt->payload;
buflen = pkt->payload_len;
service_name = sftp_msg_read_string(pkt->pool, &buf, &buflen);
pr_trace_msg(trace_channel, 10, "'%s' service requested", service_name);
cmd = pr_cmd_alloc(pkt->pool, 1, pstrdup(pkt->pool, "SERVICE_REQUEST"));
cmd->arg = service_name;
cmd->class = CL_MISC;
if (strncmp(service_name, "ssh-userauth", 13) == 0 ||
strncmp(service_name, "ssh-connection", 14) == 0) {
if (service)
*service = pstrdup(service_pool, service_name);
pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
return 0;
}
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"client requested unsupported '%s' service", service_name);
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
return -1;
}
static int write_service_accept(struct ssh2_packet *pkt, const char *service) {
char *buf, *ptr;
uint32_t buflen, bufsz = 1024;
buflen = bufsz;
ptr = buf = palloc(pkt->pool, bufsz);
sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_SERVICE_ACCEPT);
sftp_msg_write_string(&buf, &buflen, service);
pkt->payload = ptr;
pkt->payload_len = (bufsz - buflen);
return 0;
}
int sftp_service_handle(struct ssh2_packet *pkt) {
int res;
char *service = NULL;
res = read_service_req(pkt, &service);
if (res < 0) {
destroy_pool(pkt->pool);
SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, NULL);
}
destroy_pool(pkt->pool);
pkt = sftp_ssh2_packet_create(service_pool);
res = write_service_accept(pkt, service);
if (res < 0) {
destroy_pool(pkt->pool);
return -1;
}
res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
if (res < 0) {
destroy_pool(pkt->pool);
return -1;
}
destroy_pool(pkt->pool);
return 0;
}
int sftp_service_init(void) {
if (service_pool == NULL) {
service_pool = make_sub_pool(sftp_pool);
pr_pool_tag(service_pool, "Service Pool");
}
return 0;
}
|