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