~ubuntu-branches/ubuntu/trusty/proftpd-dfsg/trusty

« back to all changes in this revision

Viewing changes to contrib/mod_sftp/date.c

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2011-10-06 12:57:29 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20111006125729-wiq6d3yzf2ensafj
Tags: 1.3.4~rc3-1
* New upstream pre-release.
* Refreshed all patches.
* Changed patch xferstats.holger-preiss to fix a few warnings and use
  Getopt::Std instead of the old getopts.pl which will be removed soon or
  later in perl5. Thanks lintian.
* Policy bumped to 3.9.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ProFTPD - mod_sftp date(1) simulation
 
3
 * Copyright (c) 2011 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, 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
 * $Id: date.c,v 1.1 2011/05/24 20:55:50 castaglia Exp $
 
25
 */
 
26
 
 
27
#include "mod_sftp.h"
 
28
#include "ssh2.h"
 
29
#include "packet.h"
 
30
#include "msg.h"
 
31
#include "channel.h"
 
32
#include "date.h"
 
33
#include "misc.h"
 
34
#include "disconnect.h"
 
35
 
 
36
static pool *date_pool = NULL;
 
37
static int date_use_gmt = FALSE;
 
38
 
 
39
/* Use a struct to maintain the per-channel date-specific values. */
 
40
struct date_session {
 
41
  struct date_session *next, *prev;
 
42
 
 
43
  pool *pool;
 
44
  uint32_t channel_id;
 
45
  int use_gmt;
 
46
};
 
47
 
 
48
static struct date_session *date_sessions = NULL;
 
49
 
 
50
static const char *trace_channel = "ssh2";
 
51
 
 
52
static struct date_session *date_get_session(uint32_t channel_id) {
 
53
  struct date_session *sess;
 
54
 
 
55
  sess = date_sessions;
 
56
  while (sess) {
 
57
    pr_signals_handle();
 
58
 
 
59
    if (sess->channel_id == channel_id) {
 
60
      return sess;
 
61
    }
 
62
 
 
63
    sess = sess->next;
 
64
  }
 
65
 
 
66
  errno = ENOENT;
 
67
  return NULL;
 
68
}
 
69
 
 
70
/* Main entry point */
 
71
int sftp_date_handle_packet(pool *p, void *ssh2, uint32_t channel_id,
 
72
    char *data, uint32_t datalen) {
 
73
 
 
74
  (void) ssh2;
 
75
  (void) channel_id;
 
76
  (void) data;
 
77
  (void) datalen;
 
78
 
 
79
  /* This callback should never be called; the client will request an
 
80
   * 'exec date' command, and mod_sftp should send the channel data back
 
81
   * immediately, without needing anything more from the client.
 
82
   *
 
83
   * Thus this is essentially a no-op.
 
84
   */
 
85
 
 
86
  return 0;
 
87
}
 
88
 
 
89
int sftp_date_set_params(pool *p, uint32_t channel_id, array_header *req) {
 
90
  char **reqargv = NULL;
 
91
  int optc;
 
92
  const char *opts = "u";
 
93
 
 
94
  if (!(sftp_services & SFTP_SERVICE_FL_DATE)) {
 
95
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "%s",
 
96
      "'date' exec request denied by Protocols config");
 
97
    errno = EPERM;
 
98
    return -1;
 
99
  }
 
100
 
 
101
  reqargv = (char **) req->elts;
 
102
 
 
103
  if (pr_trace_get_level(trace_channel) >= 5) {
 
104
    register unsigned int i;
 
105
 
 
106
    for (i = 0; i < req->nelts; i++) {
 
107
      if (reqargv[i]) {
 
108
        pr_trace_msg(trace_channel, 5, "reqargv[%u] = '%s'", i, reqargv[i]);
 
109
      }
 
110
    }
 
111
  }
 
112
 
 
113
  /* Possible options are:
 
114
   *
 
115
   *  -u (GMT time)
 
116
   */
 
117
 
 
118
  pr_getopt_reset();
 
119
 
 
120
  while ((optc = getopt(req->nelts-1, reqargv, opts)) != -1) {
 
121
    switch (optc) {
 
122
      case 'u':
 
123
        date_use_gmt = TRUE;
 
124
        break;
 
125
 
 
126
      case '?':
 
127
        /* Ignore unsupported options */
 
128
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
 
129
          "ingoring supported date(1) option '%c'", (char) optopt);
 
130
        break;
 
131
    }
 
132
  }
 
133
 
 
134
  date_pool = make_sub_pool(sftp_pool);
 
135
  pr_pool_tag(date_pool, "SSH2 Date Pool");
 
136
 
 
137
  return 0;
 
138
}
 
139
 
 
140
int sftp_date_postopen_session(uint32_t channel_id) {
 
141
  struct date_session *sess;
 
142
  char *buf, *ptr;
 
143
  const char *date_str;
 
144
  uint32_t buflen, bufsz;
 
145
  time_t now;
 
146
 
 
147
  sess = date_get_session(channel_id);
 
148
  if (sess == NULL) {
 
149
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
 
150
      "no existing date(1) session for channel ID %lu, rejecting request",
 
151
      (unsigned long) channel_id);
 
152
    return -1;
 
153
  }
 
154
 
 
155
  time(&now);
 
156
  date_str = pr_strtime2(now, sess->use_gmt);
 
157
 
 
158
  /* XXX Is this big enough?  Too big? */
 
159
  buflen = bufsz = 128;
 
160
  buf = ptr = palloc(sess->pool, bufsz);
 
161
 
 
162
  /* pr_strtime() trims off the trailing newline, so add it back in. */
 
163
  sftp_msg_write_string(&buf, &buflen,
 
164
    pstrcat(sess->pool, date_str, "\n", NULL));
 
165
 
 
166
  if (sftp_channel_write_data(sess->pool, channel_id, ptr,
 
167
      (bufsz - buflen)) < 0) {
 
168
    return -1;
 
169
  }
 
170
 
 
171
  /* Return 1 to indicate that we're already done with this channel. */
 
172
  return 1;
 
173
}
 
174
 
 
175
int sftp_date_open_session(uint32_t channel_id) {
 
176
  pool *sub_pool;
 
177
  struct date_session *sess, *last;
 
178
 
 
179
  /* Check to see if we already have an date session opened for the given
 
180
   * channel ID.
 
181
   */
 
182
  sess = last = date_sessions;
 
183
  while (sess) {
 
184
    pr_signals_handle();
 
185
 
 
186
    if (sess->channel_id == channel_id) {
 
187
      errno = EEXIST;
 
188
      return -1;
 
189
    }
 
190
 
 
191
    if (sess->next == NULL) {
 
192
      /* This is the last item in the list. */
 
193
      last = sess;
 
194
    }
 
195
 
 
196
    sess = sess->next;
 
197
  }
 
198
 
 
199
  /* Looks like we get to allocate a new one. */
 
200
  sub_pool = make_sub_pool(date_pool);
 
201
  pr_pool_tag(sub_pool, "date session pool");
 
202
 
 
203
  sess = pcalloc(sub_pool, sizeof(struct date_session));
 
204
  sess->pool = sub_pool;
 
205
  sess->channel_id = channel_id;
 
206
  sess->use_gmt = date_use_gmt;
 
207
 
 
208
  if (last) {
 
209
    last->next = sess;
 
210
    sess->prev = last;
 
211
 
 
212
  } else {
 
213
    date_sessions = sess;
 
214
  }
 
215
 
 
216
  return 0;
 
217
}
 
218
 
 
219
int sftp_date_close_session(uint32_t channel_id) {
 
220
  /* no-op */
 
221
  return 0;
 
222
}