1 /*
2 * ProFTPD - mod_sftp services
3 * Copyright (c) 2008-2015 TJ Saunders
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 *
19 * As a special exemption, TJ Saunders and other respective copyright holders
20 * give permission to link this program with OpenSSL, and distribute the
21 * resulting executable, without including the source code for OpenSSL in the
22 * source distribution.
23 */
24
25 #include "mod_sftp.h"
26 #include "ssh2.h"
27 #include "service.h"
28 #include "msg.h"
29 #include "packet.h"
30 #include "disconnect.h"
31
32 static pool *service_pool = NULL;
33 static const char *trace_channel = "ssh2";
34
read_service_req(struct ssh2_packet * pkt,char ** service)35 static int read_service_req(struct ssh2_packet *pkt, char **service) {
36 unsigned char *buf;
37 char *service_name;
38 uint32_t buflen;
39 cmd_rec *cmd;
40
41 buf = pkt->payload;
42 buflen = pkt->payload_len;
43
44 service_name = sftp_msg_read_string(pkt->pool, &buf, &buflen);
45 pr_trace_msg(trace_channel, 10, "'%s' service requested", service_name);
46
47 cmd = pr_cmd_alloc(pkt->pool, 1, pstrdup(pkt->pool, "SERVICE_REQUEST"),
48 pstrdup(pkt->pool, service_name));
49 cmd->arg = service_name;
50 cmd->cmd_class = CL_MISC|CL_SSH;
51
52 if (strncmp(service_name, "ssh-userauth", 13) == 0 ||
53 strncmp(service_name, "ssh-connection", 14) == 0) {
54 if (service)
55 *service = pstrdup(service_pool, service_name);
56
57 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
58 return 0;
59 }
60
61 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
62 "client requested unsupported '%s' service", service_name);
63
64 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
65 return -1;
66 }
67
write_service_accept(struct ssh2_packet * pkt,const char * service)68 static int write_service_accept(struct ssh2_packet *pkt, const char *service) {
69 unsigned char *buf, *ptr;
70 uint32_t buflen, bufsz = 1024;
71
72 buflen = bufsz;
73 ptr = buf = palloc(pkt->pool, bufsz);
74
75 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_SERVICE_ACCEPT);
76 sftp_msg_write_string(&buf, &buflen, service);
77
78 pkt->payload = ptr;
79 pkt->payload_len = (bufsz - buflen);
80
81 return 0;
82 }
83
sftp_service_handle(struct ssh2_packet * pkt)84 int sftp_service_handle(struct ssh2_packet *pkt) {
85 int res;
86 char *service = NULL;
87
88 res = read_service_req(pkt, &service);
89 if (res < 0) {
90 destroy_pool(pkt->pool);
91 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, NULL);
92 }
93
94 destroy_pool(pkt->pool);
95
96 pkt = sftp_ssh2_packet_create(service_pool);
97 res = write_service_accept(pkt, service);
98 if (res < 0) {
99 destroy_pool(pkt->pool);
100 return -1;
101 }
102
103 res = sftp_ssh2_packet_write(sftp_conn->wfd, pkt);
104 if (res < 0) {
105 destroy_pool(pkt->pool);
106 return -1;
107 }
108
109 destroy_pool(pkt->pool);
110 return 0;
111 }
112
sftp_service_init(void)113 int sftp_service_init(void) {
114 if (service_pool == NULL) {
115 service_pool = make_sub_pool(sftp_pool);
116 pr_pool_tag(service_pool, "Service Pool");
117 }
118
119 return 0;
120 }
121