• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

proftpd / proftpd / 28042938174

23 Jun 2026 05:02PM UTC coverage: 92.464% (-0.6%) from 93.027%
28042938174

push

github

web-flow
It is possible for a client to say that it wishes to use the "sk-ssh-ed25519@openssh.com" algorithm for SSH user publickey authentication, but to _actually_ provide an "ssh-ed25519" public key.

The issue is that, when verifying the type of the public key provided by the client, we do not enforce that the provided key algorith matches the expected public key algorithm.

Thanks to Fabian Wahle of Hap Security for reporting this issue.

48661 of 52627 relevant lines covered (92.46%)

234.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.53
/tests/api/data.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2015-2026 The ProFTPD Project team
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, see <https://www.gnu.org/licenses/>.
17
 *
18
 * As a special exemption, The ProFTPD Project team and other respective
19
 * copyright holders give permission to link this program with OpenSSL, and
20
 * distribute the resulting executable, without including the source code for
21
 * OpenSSL in the source distribution.
22
 */
23

24
/* Data API tests */
25

26
#include "tests.h"
27

28
static pool *p = NULL;
29

30
static const char *data_test_path = "/tmp/prt-data.dat";
31

32
static void set_up(void) {
20✔
33
  if (p == NULL) {
20✔
34
    p = session.pool = permanent_pool = make_sub_pool(NULL);
20✔
35
  }
36

37
  init_fs();
20✔
38
  init_netio();
20✔
39
  init_config();
20✔
40
  init_dirtree();
20✔
41

42
  pr_parser_prepare(p, NULL);
20✔
43

44
  pr_response_set_pool(p);
20✔
45
  (void) pr_fsio_unlink(data_test_path);
20✔
46

47
  if (session.c != NULL) {
20✔
48
    pr_inet_close(p, session.c);
×
49
    session.c = NULL;
×
50
  }
51

52
  session.sf_flags = 0;
20✔
53

54
  pr_trace_set_levels("timing", 1, 1);
20✔
55
  if (getenv("TEST_VERBOSE") != NULL) {
20✔
56
    pr_trace_set_levels("data", 1, 20);
20✔
57
  }
58
}
20✔
59

60
static void tear_down(void) {
20✔
61
  (void) pr_fsio_unlink(data_test_path);
20✔
62

63
  if (session.c != NULL) {
20✔
64
    (void) pr_inet_close(p, session.c);
6✔
65
  }
66

67
  if (session.d != NULL &&
26✔
68
      session.d != session.c) {
6✔
69
    (void) pr_inet_close(p, session.d);
6✔
70
  }
71

72
  session.c = session.d = NULL;
20✔
73

74
  pr_unregister_netio(PR_NETIO_STRM_CTRL|PR_NETIO_STRM_CTRL);
20✔
75
  pr_unregister_netio(PR_NETIO_STRM_CTRL|PR_NETIO_STRM_DATA);
20✔
76

77
  if (getenv("TEST_VERBOSE") != NULL) {
20✔
78
    pr_trace_set_levels("data", 0, 0);
20✔
79
  }
80
  pr_trace_set_levels("timing", 0, 0);
20✔
81

82
  pr_parser_cleanup();
20✔
83
  pr_response_set_pool(NULL);
20✔
84

85
  if (p == NULL) {
20✔
86
    destroy_pool(p);
×
87
    p = session.pool = session.xfer.p = permanent_pool = NULL;
×
88
  }
89
}
20✔
90

91
static int tmpfile_fd(void) {
1✔
92
  int fd;
93

94
  fd = open(data_test_path, O_CREAT|O_RDWR, 0600);
2✔
95
  if (fd < 0) {
1✔
96
    fprintf(stderr, "Error opening %s: %s\n", data_test_path, strerror(errno));
×
97
    return -1;
×
98
  }
99

100
  (void) unlink(data_test_path);
1✔
101
  return fd;
1✔
102
}
103

104
static int rewind_fd(int fd) {
105
  if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
1✔
106
    return -1;
107
  }
108

109
  return 0;
110
}
111

112
START_TEST (data_get_timeout_test) {
1✔
113
  int res;
114

115
  res = pr_data_get_timeout(-1);
1✔
116
  ck_assert_msg(res < 0, "Failed to handle invalid timeout ID");
1✔
117
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
118
    strerror(errno), errno);
119

120
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_IDLE);
1✔
121
  ck_assert_msg(res == PR_TUNABLE_TIMEOUTIDLE, "Expected %d, got %d",
2✔
122
    PR_TUNABLE_TIMEOUTIDLE, res);
123

124
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER);
1✔
125
  ck_assert_msg(res == PR_TUNABLE_TIMEOUTNOXFER, "Expected %d, got %d",
2✔
126
    PR_TUNABLE_TIMEOUTNOXFER, res);
127

128
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED);
1✔
129
  ck_assert_msg(res == PR_TUNABLE_TIMEOUTSTALLED, "Expected %d, got %d",
2✔
130
    PR_TUNABLE_TIMEOUTSTALLED, res);
131
}
132
END_TEST
1✔
133

134
START_TEST (data_set_timeout_test) {
1✔
135
  int res, timeout = 7;
1✔
136

137
  pr_data_set_timeout(PR_DATA_TIMEOUT_IDLE, timeout);
1✔
138
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_IDLE);
1✔
139
  ck_assert_msg(res == timeout, "Expected %d, got %d", timeout, res);
1✔
140

141
  pr_data_set_timeout(PR_DATA_TIMEOUT_NO_TRANSFER, timeout);
1✔
142
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER);
1✔
143
  ck_assert_msg(res == timeout, "Expected %d, got %d", timeout, res);
2✔
144

145
  pr_data_set_timeout(PR_DATA_TIMEOUT_STALLED, timeout);
1✔
146
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED);
1✔
147
  ck_assert_msg(res == timeout, "Expected %d, got %d", timeout, res);
2✔
148

149
  /* Interestingly, the linger timeout has its own function. */
150
  pr_data_set_linger(7L);
1✔
151
}
152
END_TEST
1✔
153

154
START_TEST (data_ignore_ascii_test) {
1✔
155
  int res;
156

157
  res = pr_data_ignore_ascii(-1);
1✔
158
  ck_assert_msg(res < 0, "Failed to handle invalid argument");
1✔
159
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
160
    strerror(errno), errno);
161

162
  res = pr_data_ignore_ascii(TRUE);
1✔
163
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
2✔
164

165
  res = pr_data_ignore_ascii(TRUE);
1✔
166
  ck_assert_msg(res == TRUE, "Expected TRUE (%d), got %d", TRUE, res);
2✔
167

168
  res = pr_data_ignore_ascii(FALSE);
1✔
169
  ck_assert_msg(res == TRUE, "Expected TRUE (%d), got %d", TRUE, res);
2✔
170

171
  res = pr_data_ignore_ascii(FALSE);
1✔
172
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
2✔
173
}
174
END_TEST
1✔
175

176
static int data_close_cb(pr_netio_stream_t *nstrm) {
30✔
177
  return 0;
30✔
178
}
179

180
static int data_poll_cb(pr_netio_stream_t *nstrm) {
46✔
181
  /* Always return >0, to indicate that we haven't timed out, AND that there
182
   * is a writable fd available.
183
   */
184
  return 7;
46✔
185
}
186

187
static int data_read_eagain = FALSE;
188
static int data_read_epipe = FALSE;
189
static int data_read_dangling_cr = FALSE;
190

191
static int data_read_cb(pr_netio_stream_t *nstrm, char *buf, size_t buflen) {
11✔
192
  const char *data = "Hello,\r\n World!\r\n";
11✔
193
  size_t sz;
194

195
  if (data_read_eagain) {
11✔
196
    data_read_eagain = FALSE;
1✔
197
    errno = EAGAIN;
1✔
198
    return -1;
1✔
199
  }
200

201
  if (data_read_epipe) {
10✔
202
    data_read_epipe = FALSE;
×
203
    errno = EPIPE;
×
204
    return -1;
×
205
  }
206

207
  if (data_read_dangling_cr) {
10✔
208
    data = "Hello,\r\n World!\r\n\r";
1✔
209
  }
210

211
  sz = strlen(data);
10✔
212
  if (buflen < sz) {
10✔
213
    sz = buflen;
×
214
  }
215

216
  memcpy(buf, data, sz);
10✔
217
  return (int) sz;
10✔
218
}
219

220
static int data_write_eagain = FALSE;
221
static int data_write_epipe = FALSE;
222

223
static int data_write_cb(pr_netio_stream_t *nstrm, char *buf, size_t buflen) {
21✔
224
  if (data_write_eagain) {
21✔
225
    data_write_eagain = FALSE;
5✔
226
    errno = EAGAIN;
5✔
227
    return -1;
5✔
228
  }
229

230
  if (data_write_epipe) {
16✔
231
    data_write_epipe = FALSE;
×
232
    errno = EPIPE;
×
233
    return -1;
×
234
  }
235

236
  return buflen;
16✔
237
}
238

239
static int data_open_streams(conn_t *conn, int strm_type) {
15✔
240
  int fd = 2, res;
15✔
241
  pr_netio_t *netio;
242
  pr_netio_stream_t *nstrm;
243

244
  netio = pr_alloc_netio2(p, NULL, "testsuite");
15✔
245
  netio->close = data_close_cb;
15✔
246
  netio->poll = data_poll_cb;
15✔
247
  netio->read = data_read_cb;
15✔
248
  netio->write = data_write_cb;
15✔
249

250
  res = pr_register_netio(netio, strm_type);
15✔
251
  if (res < 0) {
15✔
252
    return -1;
253
  }
254

255
  nstrm = pr_netio_open(p, strm_type, fd, PR_NETIO_IO_WR);
15✔
256
  if (nstrm == NULL) {
15✔
257
    return -1;
258
  }
259

260
  conn->outstrm = nstrm;
15✔
261

262
  nstrm = pr_netio_open(p, strm_type, fd, PR_NETIO_IO_RD);
15✔
263
  if (nstrm == NULL) {
15✔
264
    return -1;
265
  }
266

267
  conn->instrm = nstrm;
15✔
268
  return 0;
269
}
270

271
START_TEST (data_sendfile_test) {
1✔
272
  int fd = -1, res;
1✔
273
  off_t offset = 0;
1✔
274
  pr_fh_t *fh;
275
  const char *text;
276

277
  res = (int) pr_data_sendfile(fd, NULL, 0);
1✔
278
  if (res < 0 &&
2✔
279
      errno == ENOSYS) {
1✔
280
    return;
×
281
  }
282

283
  res = pr_data_sendfile(fd, NULL, 0);
1✔
284
  ck_assert_msg(res < 0, "Failed to handle null offset");
1✔
285
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
286
    strerror(errno), errno);
287

288
  res = pr_data_sendfile(fd, &offset, 0);
1✔
289
  ck_assert_msg(res < 0, "Failed to handle zero count");
2✔
290
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
291
    strerror(errno), errno);
292

293
  session.xfer.direction = PR_NETIO_IO_RD;
1✔
294
  res = pr_data_sendfile(fd, &offset, 1);
1✔
295
  ck_assert_msg(res < 0, "Failed to handle invalid transfer direction");
2✔
296
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
2✔
297
    strerror(errno), errno);
298

299
  session.xfer.direction = PR_NETIO_IO_WR;
1✔
300
  res = pr_data_sendfile(fd, &offset, 1);
1✔
301
  ck_assert_msg(res < 0, "Failed to handle lack of data connection");
2✔
302
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
2✔
303
    strerror(errno), errno);
304

305
  mark_point();
1✔
306
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
307
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
308

309
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
310
  ck_assert_msg(res == 0, "Failed to open streams: %s", strerror(errno));
2✔
311

312
  mark_point();
1✔
313
  res = pr_data_sendfile(fd, &offset, 1);
1✔
314
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
2✔
315
  ck_assert_msg(errno == EBADF || errno == EINVAL,
2✔
316
    "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
317
    strerror(errno), errno);
318

319
  fh = pr_fsio_open(data_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
320
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", data_test_path,
2✔
321
    strerror(errno));
322

323
  text = "Hello, World!\n";
1✔
324
  res = pr_fsio_write(fh, text, strlen(text));
1✔
325
  ck_assert_msg(res >= 0, "Failed to write to '%s': %s", data_test_path,
2✔
326
    strerror(errno));
327
  res = pr_fsio_close(fh);
1✔
328
  ck_assert_msg(res == 0, "Failed to close '%s': %s", data_test_path,
2✔
329
    strerror(errno));
330

331
  fd = open(data_test_path, O_RDONLY);
2✔
332
  ck_assert_msg(fd >= 0, "Failed to open '%s': %s", data_test_path,
2✔
333
    strerror(errno));
334

335
  mark_point();
1✔
336
  res = pr_data_sendfile(fd, &offset, strlen(text));
1✔
337
  if (res < 0) {
1✔
338
    ck_assert_msg(errno == ENOTSOCK || errno == EINVAL,
×
339
     "Expected ENOTSOCK (%d) or EINVAL (%d), got %s (%d)", ENOTSOCK, EINVAL,
340
     strerror(errno), errno);
341
  }
342

343
  (void) close(fd);
1✔
344
  (void) pr_netio_close(session.d->outstrm);
1✔
345
  session.d->outstrm = NULL;
1✔
346
  (void) pr_inet_close(p, session.d);
1✔
347
  session.d = NULL;
1✔
348

349
  pr_unregister_netio(PR_NETIO_STRM_DATA);
1✔
350
}
351
END_TEST
352

353
START_TEST (data_init_test) {
1✔
354
  int rd = PR_NETIO_IO_RD, wr = PR_NETIO_IO_WR;
1✔
355
  char *filename = NULL;
1✔
356

357
  mark_point();
1✔
358
  pr_data_init(filename, 0);
1✔
359
  ck_assert_msg(session.xfer.direction == 0, "Expected xfer direction %d, got %d",
1✔
360
    0, session.xfer.direction);
361
  ck_assert_msg(session.xfer.p != NULL, "Transfer pool not created as expected");
2✔
362
  ck_assert_msg(session.xfer.filename == NULL, "Expected null filename, got %s",
2✔
363
    session.xfer.filename);
364

365
  filename = "test.dat";
1✔
366
  pr_data_clear_xfer_pool();
1✔
367

368
  mark_point();
1✔
369
  pr_data_init(filename, rd);
1✔
370
  ck_assert_msg(session.xfer.direction == rd,
2✔
371
    "Expected xfer direction %d, got %d", rd, session.xfer.direction);
372
  ck_assert_msg(session.xfer.p != NULL, "Transfer pool not created as expected");
2✔
373
  ck_assert_msg(session.xfer.filename != NULL, "Missing transfer filename");
2✔
374
  ck_assert_msg(strcmp(session.xfer.filename, filename) == 0,
2✔
375
    "Expected '%s', got '%s'", filename, session.xfer.filename);
376

377
  mark_point();
1✔
378
  pr_data_init("test2.dat", wr);
1✔
379
  ck_assert_msg(session.xfer.direction == wr,
2✔
380
    "Expected xfer direction %d, got %d", wr, session.xfer.direction);
381
  ck_assert_msg(session.xfer.p != NULL, "Transfer pool not created as expected");
2✔
382
  ck_assert_msg(session.xfer.filename != NULL, "Missing transfer filename");
2✔
383

384
  /* Even though we opened with a new filename, the previous filename should
385
   * still be there, as we didn't actually clear/reset this transfer.
386
   */
387
  ck_assert_msg(strcmp(session.xfer.filename, filename) == 0,
2✔
388
    "Expected '%s', got '%s'", filename, session.xfer.filename);
389
}
390
END_TEST
1✔
391

392
START_TEST (data_open_active_test) {
1✔
393
  int dir = PR_NETIO_IO_RD, port = INPORT_ANY, sockfd = -1, res;
1✔
394
  conn_t *conn;
395

396
  mark_point();
1✔
397
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
398
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
399
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
400
    strerror(errno), errno);
401

402
  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
403
  ck_assert_msg(conn != NULL, "Failed to create conn: %s", strerror(errno));
2✔
404

405
  /* Note: these tests REQUIRE that session.c be non-NULL */
406
  session.c = conn;
1✔
407

408
  /* Open a READing data transfer connection...*/
409

410
  mark_point();
1✔
411
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
412
  ck_assert_msg(res < 0, "Failed to handle null arguments");
2✔
413
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
414
    strerror(errno), errno);
415

416
  /* Note: we also need session.c to have valid local/remote_addr, too! */
417
  session.c->local_addr = session.c->remote_addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
1✔
418
  ck_assert_msg(session.c->remote_addr != NULL, "Failed to get address: %s",
2✔
419
    strerror(errno));
420

421
  mark_point();
1✔
422
  session.d = session.c;
1✔
423
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
424
  ck_assert_msg(res < 0, "Failed to handle non-null session.d");
2✔
425
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
426
    strerror(errno), errno);
427
  session.d = NULL;
1✔
428

429
  mark_point();
1✔
430
  session.xfer.filename = "foo";
1✔
431
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
432
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
433
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
2✔
434
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
435
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
436
  session.xfer.filename = NULL;
1✔
437

438
  /* Open a WRITing data transfer connection...*/
439
  dir = PR_NETIO_IO_WR;
1✔
440

441
  mark_point();
1✔
442
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
443
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
444
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
2✔
445
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
446
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
447

448
  mark_point();
1✔
449
  session.xfer.p = NULL;
1✔
450
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
451
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
452
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
2✔
453
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
454
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
455

456
  (void) pr_inet_close(p, session.c);
1✔
457
  session.c = NULL;
1✔
458
  if (session.d != NULL) {
1✔
459
    (void) pr_inet_close(p, session.d);
×
460
    session.d = NULL;
×
461
  }
462
}
463
END_TEST
1✔
464

465
START_TEST (data_open_active_rootrevoke_test) {
1✔
466
  int dir = PR_NETIO_IO_RD, local_port, port = INPORT_ANY, sockfd = -1, res;
1✔
467
  conn_t *conn;
468
  config_rec *c;
469
  server_rec *s;
470

471
  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
472
  ck_assert_msg(conn != NULL, "Failed to create conn: %s", strerror(errno));
1✔
473

474
  /* Note: these tests REQUIRE that session.c be non-NULL */
475
  session.c = conn;
1✔
476

477
  /* Note: we also need session.c to have valid local/remote_addr, too! */
478
  session.c->local_addr = session.c->remote_addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
1✔
479
  ck_assert_msg(session.c->remote_addr != NULL, "Failed to get address: %s",
2✔
480
    strerror(errno));
481

482
  s = pr_parser_server_ctxt_open("127.0.0.1");
1✔
483
  c = add_config_param("RootRevoke", 1, NULL);
1✔
484
  c->argv[0] = palloc(c->pool, sizeof(int));
1✔
485
  *((int *) c->argv[0]) = 1;
1✔
486

487
  tests_stubs_set_main_server(s);
1✔
488

489
  mark_point();
1✔
490
  session.xfer.filename = "foo";
1✔
491
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
492
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
493
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
2✔
494
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
495
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
496
  session.xfer.filename = NULL;
1✔
497

498
  mark_point();
1✔
499
  local_port = session.c->local_port;
1✔
500
  session.c->local_port = 21;
1✔
501
  session.xfer.filename = "foo";
1✔
502
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
503
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
504
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
2✔
505
    strerror(errno), errno);
506
  session.c->local_port = local_port;
1✔
507
  session.xfer.filename = NULL;
1✔
508

509
  mark_point();
1✔
510
  *((int *) c->argv[0]) = 2;
1✔
511
  session.xfer.filename = "foo";
1✔
512
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
513
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
514
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
2✔
515
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
516
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
517
  session.xfer.filename = NULL;
1✔
518

519
  mark_point();
1✔
520
  *((int *) c->argv[0]) = 3;
1✔
521
  session.xfer.filename = "foo";
1✔
522
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
523
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
2✔
524
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
2✔
525
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
526
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
527
  session.xfer.filename = NULL;
1✔
528

529
  (void) pr_config_remove(s->conf, "RootRevoke", 0, FALSE);
1✔
530

531
  (void) pr_inet_close(p, session.c);
1✔
532
  session.c = NULL;
1✔
533
  if (session.d != NULL) {
1✔
534
    (void) pr_inet_close(p, session.d);
×
535
    session.d = NULL;
×
536
  }
537

538
  tests_stubs_set_main_server(NULL);
1✔
539
}
540
END_TEST
1✔
541

542
START_TEST (data_open_passive_test) {
1✔
543
  int dir = PR_NETIO_IO_RD, fd, port = INPORT_ANY, sockfd = -1, res;
1✔
544
  conn_t *data_conn;
545

546
  /* Set the session flags for a passive transfer data connection. */
547
  session.sf_flags |= SF_PASSIVE;
1✔
548

549
  mark_point();
1✔
550
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
551
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
552
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
553
    strerror(errno), errno);
554

555
  /* Note: these tests REQUIRE that session.c be non-NULL, AND that session.d
556
   * be non-NULL.
557
   */
558
  session.c = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
559
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s",
2✔
560
    strerror(errno));
561

562
  session.d = data_conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
563
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s",
2✔
564
    strerror(errno));
565

566
  /* Reset the session flags after every failed open. */
567
  session.sf_flags |= SF_PASSIVE;
1✔
568

569
  /* Open a READing data transfer connection...*/
570

571
  mark_point();
1✔
572
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
573
  ck_assert_msg(res < 0, "Failed to handle null arguments");
2✔
574
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
575
    strerror(errno), errno);
576

577
  /* Note: we also need session.c to have valid local/remote_addr, too! */
578
  session.c->local_addr = session.c->remote_addr = pr_netaddr_get_addr(p,
1✔
579
    "127.0.0.1", NULL);
580
  ck_assert_msg(session.c->remote_addr != NULL, "Failed to get address: %s",
2✔
581
    strerror(errno));
582

583
  mark_point();
1✔
584
  data_conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
585
  fd = data_conn->listen_fd;
1✔
586
  data_conn->listen_fd = dup(0);
1✔
587
  session.d = data_conn;
1✔
588
  session.sf_flags |= SF_PASSIVE;
1✔
589
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
590
  ck_assert_msg(res < 0, "Opened passive READ data connection unexpectedly");
2✔
591
  ck_assert_msg(errno == ENOTSOCK, "Expected ENOTSOCK (%d), got %s (%d)",
2✔
592
    ENOTSOCK, strerror(errno), errno);
593
  (void) close(fd);
1✔
594

595
  /* Open a WRITing data transfer connection...*/
596
  dir = PR_NETIO_IO_WR;
1✔
597

598
  mark_point();
1✔
599
  data_conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
600
  fd = data_conn->listen_fd;
1✔
601
  data_conn->listen_fd = dup(1);
1✔
602
  session.d = data_conn;
1✔
603
  session.sf_flags |= SF_PASSIVE;
1✔
604
  session.xfer.p = NULL;
1✔
605
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
606
  ck_assert_msg(res < 0, "Opened passive WRITE data connection unexpectedly");
2✔
607
  ck_assert_msg(errno == ENOTSOCK, "Expected ENOTSOCK (%d), got %s (%d)",
2✔
608
    ENOTSOCK, strerror(errno), errno);
609
  (void) close(fd);
1✔
610

611
  mark_point();
1✔
612
  session.sf_flags |= SF_PASSIVE;
1✔
613
  session.xfer.p = NULL;
1✔
614
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
615
  ck_assert_msg(res < 0, "Opened passive WRITE data connection unexpectedly");
2✔
616
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
617
    strerror(errno), errno);
618

619
  (void) pr_inet_close(p, session.c);
1✔
620
  session.c = NULL;
1✔
621
  if (session.d != NULL) {
1✔
622
    (void) pr_inet_close(p, session.d);
×
623
    session.d = NULL;
×
624
  }
625
}
626
END_TEST
1✔
627

628
START_TEST (data_close_test) {
1✔
629
  session.sf_flags |= SF_PASSIVE;
1✔
630
  pr_data_close(TRUE);
1✔
631
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
632
    "Failed to clear SF_PASSIVE session flag");
633

634
  session.sf_flags |= SF_PASSIVE;
1✔
635
  pr_data_close(FALSE);
1✔
636
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
2✔
637
    "Failed to clear SF_PASSIVE session flag");
638

639
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
640
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
641

642
  pr_data_close(TRUE);
1✔
643
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
644
}
645
END_TEST
1✔
646

647
START_TEST (data_abort_test) {
1✔
648
  mark_point();
1✔
649
  session.sf_flags |= SF_PASSIVE;
1✔
650
  pr_data_abort(EPERM, TRUE);
1✔
651
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
652
    "Failed to clear SF_PASSIVE session flag");
653

654
  session.sf_flags |= SF_PASSIVE;
1✔
655
  pr_data_abort(EPERM, FALSE);
1✔
656
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
2✔
657
    "Failed to clear SF_PASSIVE session flag");
658

659
  mark_point();
1✔
660
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
661
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
662

663
  pr_data_abort(ESPIPE, FALSE);
1✔
664
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
665

666
  mark_point();
1✔
667
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
668
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
669

670
  session.sf_flags = SF_ABORT;
1✔
671
  pr_data_abort(EPIPE, FALSE);
1✔
672
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
673
  session.sf_flags &= ~SF_POST_ABORT;
1✔
674

675
#if defined(ENXIO)
676
  mark_point();
1✔
677
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
678
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
679
  pr_data_abort(ENXIO, FALSE);
1✔
680
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
681
#endif /* ENXIO */
682

683
#if defined(ENOMEM)
684
  mark_point();
1✔
685
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
686
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
687
  pr_data_abort(ENOMEM, FALSE);
1✔
688
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
689
#endif /* ENOMEM */
690

691
#if defined(EBUSY)
692
  mark_point();
1✔
693
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
694
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
695
  pr_data_abort(EBUSY, FALSE);
1✔
696
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
697
#endif /* EBUSY */
698

699
#if defined(ENOSPC)
700
  mark_point();
1✔
701
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
702
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
703
  pr_data_abort(ENOSPC, FALSE);
1✔
704
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
705
#endif /* ENOSPC */
706

707
#if defined(EFBIG)
708
  mark_point();
1✔
709
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
710
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
711
  pr_data_abort(EFBIG, FALSE);
1✔
712
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
713
#endif /* EFBIG */
714

715
#if defined(ECONNRESET)
716
  mark_point();
1✔
717
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
718
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
719
  pr_data_abort(ECONNRESET, FALSE);
1✔
720
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
721
#endif /* ECONNRESET */
722

723
  mark_point();
1✔
724
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
725
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
726
  pr_data_abort(-5432, FALSE);
1✔
727
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
728
}
729
END_TEST
1✔
730

731
START_TEST (data_reset_test) {
1✔
732
  mark_point();
1✔
733

734
  /* Set a session flag, make sure it's cleared properly. */
735
  session.sf_flags |= SF_PASSIVE;
1✔
736
  pr_data_reset();
1✔
737
  ck_assert_msg(session.d == NULL, "Expected NULL session.d, got %p", session.d);
1✔
738
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
2✔
739
    "SF_PASSIVE session flag not cleared");
740

741
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
742
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
743

744
  pr_data_reset();
1✔
745
  ck_assert_msg(session.d == NULL, "Expected NULL session.d, got %p", session.d);
2✔
746
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
2✔
747
    "SF_PASSIVE session flag not cleared");
748
}
749
END_TEST
1✔
750

751
START_TEST (data_cleanup_test) {
1✔
752
  mark_point();
1✔
753

754
  /* Set a session flag, make sure it's cleared properly. */
755
  session.sf_flags |= SF_PASSIVE;
1✔
756
  pr_data_cleanup();
1✔
757
  ck_assert_msg(session.d == NULL, "Expected NULL session.d, got %p", session.d);
1✔
758
  ck_assert_msg(session.sf_flags & SF_PASSIVE,
2✔
759
    "SF_PASSIVE session flag not preserved");
760
  ck_assert_msg(session.xfer.xfer_type == STOR_DEFAULT, "Expected %d, got %d",
2✔
761
    STOR_DEFAULT, session.xfer.xfer_type);
762

763
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
764
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
765

766
  pr_data_cleanup();
1✔
767
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
2✔
768
}
769
END_TEST
1✔
770

771
START_TEST (data_clear_xfer_pool_test) {
1✔
772
  int xfer_type = 7;
1✔
773

774
  mark_point();
1✔
775
  pr_data_clear_xfer_pool();
1✔
776
  ck_assert_msg(session.xfer.p == NULL, "Failed to clear session.xfer.p");
1✔
777

778
  session.xfer.xfer_type = xfer_type;
1✔
779
  session.xfer.p = make_sub_pool(p);
1✔
780

781
  mark_point();
1✔
782
  pr_data_clear_xfer_pool();
1✔
783
  ck_assert_msg(session.xfer.p == NULL, "Failed to clear session.xfer.p");
2✔
784
  ck_assert_msg(session.xfer.xfer_type == xfer_type, "Expected %d, got %d",
2✔
785
    xfer_type, session.xfer.xfer_type);
786
}
787
END_TEST
1✔
788

789
START_TEST (data_xfer_read_binary_test) {
1✔
790
  int res;
791
  char *buf, *expected;
792
  size_t bufsz, expected_len;
793
  cmd_rec *cmd;
794

795
  pr_data_clear_xfer_pool();
1✔
796
  pr_data_reset();
1✔
797

798
  res = pr_data_xfer(NULL, 0);
1✔
799
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
800
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
801
    strerror(errno), errno);
802

803
  bufsz = 1024;
1✔
804
  buf = palloc(p, bufsz);
1✔
805

806
  res = pr_data_xfer(buf, 0);
1✔
807
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
2✔
808
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
809
    strerror(errno), errno);
810

811
  mark_point();
1✔
812
  res = pr_data_xfer(buf, bufsz);
1✔
813
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
814
  ck_assert_msg(errno == ECONNABORTED,
2✔
815
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
816
    strerror(errno), errno);
817

818
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
819
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
820

821
  /* read binary data */
822
  session.xfer.direction = PR_NETIO_IO_RD;
1✔
823

824
  /* Note: this string comes from the data_read_cb() we register with our
825
   * DATA stream callback.
826
   */
827
  expected = "Hello,\r\n World!\r\n";
1✔
828
  expected_len = strlen(expected);
1✔
829

830
  mark_point();
1✔
831
  data_write_eagain = TRUE;
1✔
832
  session.xfer.buf = NULL;
1✔
833
  session.xfer.buflen = 0;
1✔
834

835
  res = pr_data_xfer(buf, bufsz);
1✔
836
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
837
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
838
    strerror(errno), errno);
839

840
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
841
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
842
    strerror(errno));
843

844
  mark_point();
1✔
845
  session.xfer.buf = NULL;
1✔
846
  session.xfer.buflen = 0;
1✔
847

848
  res = pr_data_xfer(buf, bufsz);
1✔
849
  ck_assert_msg((size_t) res == expected_len, "Expected %lu, got %d",
2✔
850
    (unsigned long) expected_len, res);
851

852
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
853
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
854

855
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
856
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
857
    strerror(errno));
858

859
  mark_point();
1✔
860
  session.xfer.buf = NULL;
1✔
861
  session.xfer.buflen = 0;
1✔
862

863
  res = pr_data_xfer(buf, bufsz);
1✔
864
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
865
    (unsigned long) expected_len, res);
866
  ck_assert_msg(session.xfer.buflen == 0,
2✔
867
    "Expected session.xfer.buflen 0, got %lu",
868
    (unsigned long) session.xfer.buflen);
869

870
  mark_point();
1✔
871
  session.xfer.buf = NULL;
1✔
872
  session.xfer.buflen = 0;
1✔
873
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "syst"));
1✔
874
  tests_stubs_set_next_cmd(cmd);
1✔
875
  data_read_eagain = TRUE;
1✔
876

877
  res = pr_data_xfer(buf, bufsz);
1✔
878
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
879
    (unsigned long) expected_len, res);
880
  ck_assert_msg(session.xfer.buflen == 0,
2✔
881
    "Expected session.xfer.buflen 0, got %lu",
882
    (unsigned long) session.xfer.buflen);
883
}
884
END_TEST
1✔
885

886
START_TEST (data_xfer_write_binary_test) {
1✔
887
  int res;
888
  char *buf;
889
  size_t buflen;
890

891
  pr_data_clear_xfer_pool();
1✔
892
  pr_data_reset();
1✔
893

894
  res = pr_data_xfer(NULL, 0);
1✔
895
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
896
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
897
    strerror(errno), errno);
898

899
  buf = "Hello, World!\n";
1✔
900
  buflen = strlen(buf);
1✔
901

902
  res = pr_data_xfer(buf, 0);
1✔
903
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
2✔
904
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
905
    strerror(errno), errno);
906

907
  mark_point();
1✔
908
  res = pr_data_xfer(buf, buflen);
1✔
909
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
910
  ck_assert_msg(errno == ECONNABORTED,
2✔
911
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
912
    strerror(errno), errno);
913

914
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
915
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
916

917
  /* write binary data */
918
  session.xfer.direction = PR_NETIO_IO_WR;
1✔
919
  session.xfer.p = make_sub_pool(p);
1✔
920
  session.xfer.buflen = 1024;
1✔
921
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
922

923
  mark_point();
1✔
924
  data_write_eagain = TRUE;
1✔
925
  res = pr_data_xfer(buf, buflen);
1✔
926
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
927
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
928
    strerror(errno), errno);
929

930
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
931
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
932
    strerror(errno));
933

934
  mark_point();
1✔
935
  res = pr_data_xfer(buf, buflen);
1✔
936
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
937
    (unsigned long) buflen, res);
938

939
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
940
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
941

942
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
943
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
944
    strerror(errno));
945

946
  mark_point();
1✔
947
  res = pr_data_xfer(buf, buflen);
1✔
948
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
949
    (unsigned long) buflen, res);
950

951
  /* Now that we no longer do an egregious memcpy() into session.xfer.buf
952
   * for binary transfers, we cannot use the contents of session.xfer.buf
953
   * for additional assertions.  The integration tests can cover those
954
   * assertions.
955
   */
956
}
957
END_TEST
1✔
958

959
START_TEST (data_xfer_read_ascii_test) {
1✔
960
  int res;
961
  char *buf, *expected;
962
  size_t bufsz, expected_len;
963
  cmd_rec *cmd;
964

965
  pr_data_clear_xfer_pool();
1✔
966
  pr_data_reset();
1✔
967

968
  res = pr_data_xfer(NULL, 0);
1✔
969
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
970
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
971
    strerror(errno), errno);
972

973
  bufsz = 1024;
1✔
974
  buf = palloc(p, bufsz);
1✔
975

976
  res = pr_data_xfer(buf, 0);
1✔
977
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
2✔
978
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
979
    strerror(errno), errno);
980

981
  mark_point();
1✔
982
  res = pr_data_xfer(buf, bufsz);
1✔
983
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
984
  ck_assert_msg(errno == ECONNABORTED,
2✔
985
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
986
    strerror(errno), errno);
987

988
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
989
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
990

991
  /* read ASCII data */
992
  session.xfer.direction = PR_NETIO_IO_RD;
1✔
993
  session.xfer.p = make_sub_pool(p);
1✔
994
  session.xfer.bufsize = 1024;
1✔
995

996
  /* Note: this string comes from the data_read_cb() we register with our
997
   * DATA stream callback.
998
   */
999
  expected = "Hello,\n World!\n";
1✔
1000
  expected_len = strlen(expected);
1✔
1001

1002
  mark_point();
1✔
1003
  data_write_eagain = TRUE;
1✔
1004
  pr_ascii_ftp_reset();
1✔
1005
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1006
  session.xfer.buflen = 0;
1✔
1007

1008
  session.sf_flags |= SF_ASCII;
1✔
1009
  res = pr_data_xfer(buf, bufsz);
1✔
1010
  session.sf_flags &= ~SF_ASCII;
1✔
1011

1012
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
1013
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1014
    strerror(errno), errno);
1015

1016
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
1017
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
1018
    strerror(errno));
1019

1020
  mark_point();
1✔
1021
  pr_ascii_ftp_reset();
1✔
1022
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1023
  session.xfer.buflen = 0;
1✔
1024

1025
  session.sf_flags |= SF_ASCII;
1✔
1026
  res = pr_data_xfer(buf, bufsz);
1✔
1027
  session.sf_flags &= ~SF_ASCII;
1✔
1028

1029
  ck_assert_msg((size_t) res == expected_len, "Expected %lu, got %d",
2✔
1030
    (unsigned long) expected_len, res);
1031

1032
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1033
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
1034

1035
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
1036
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
1037
    strerror(errno));
1038

1039
  mark_point();
1✔
1040
  pr_ascii_ftp_reset();
1✔
1041
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1042
  session.xfer.buflen = 0;
1✔
1043

1044
  session.sf_flags |= SF_ASCII;
1✔
1045
  res = pr_data_xfer(buf, bufsz);
1✔
1046
  session.sf_flags &= ~SF_ASCII;
1✔
1047

1048
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
1049
    (unsigned long) expected_len, res);
1050
  ck_assert_msg(session.xfer.buflen == 0,
2✔
1051
    "Expected session.xfer.buflen 0, got %lu",
1052
    (unsigned long) session.xfer.buflen);
1053
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
2✔
1054
    "Expected '%s', got '%.100s'", expected, buf);
1055

1056
  mark_point();
1✔
1057
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "noop"));
1✔
1058
  tests_stubs_set_next_cmd(cmd);
1✔
1059
  pr_ascii_ftp_reset();
1✔
1060
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1061
  session.xfer.buflen = 0;
1✔
1062

1063
  session.sf_flags |= SF_ASCII;
1✔
1064
  res = pr_data_xfer(buf, bufsz);
1✔
1065
  session.sf_flags &= ~SF_ASCII;
1✔
1066

1067
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
1068
    (unsigned long) expected_len, res);
1069
  ck_assert_msg(session.xfer.buflen == 0,
2✔
1070
    "Expected session.xfer.buflen 0, got %lu",
1071
    (unsigned long) session.xfer.buflen);
1072
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
2✔
1073
    "Expected '%s', got '%.100s'", expected, buf);
1074

1075
  mark_point();
1✔
1076
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "pasv"));
1✔
1077
  tests_stubs_set_next_cmd(cmd);
1✔
1078
  pr_ascii_ftp_reset();
1✔
1079
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1080
  session.xfer.buflen = 0;
1✔
1081

1082
  session.sf_flags |= SF_ASCII;
1✔
1083
  res = pr_data_xfer(buf, bufsz);
1✔
1084
  session.sf_flags &= ~SF_ASCII;
1✔
1085

1086
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
1087
    (unsigned long) expected_len, res);
1088
  ck_assert_msg(session.xfer.buflen == 0,
2✔
1089
    "Expected session.xfer.buflen 0, got %lu",
1090
    (unsigned long) session.xfer.buflen);
1091
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
2✔
1092
    "Expected '%s', got '%.100s'", expected, buf);
1093

1094
  /* Bug#4237 happened because of insufficient testing of the edge case
1095
   * where the LAST character in the buffer is a CR.
1096
   *
1097
   * Note that to properly test this, we need to KEEP the same session.xfer.buf
1098
   * in place, and do the read TWICE (at least; maybe more).
1099
   */
1100

1101
  mark_point();
1✔
1102
  pr_ascii_ftp_reset();
1✔
1103
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1104
  session.xfer.buflen = 0;
1✔
1105
  data_read_dangling_cr = TRUE;
1✔
1106

1107
  session.sf_flags |= SF_ASCII;
1✔
1108
  res = pr_data_xfer(buf, bufsz);
1✔
1109
  session.sf_flags &= ~SF_ASCII;
1✔
1110

1111
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
1112
    (unsigned long) expected_len, res);
1113
  ck_assert_msg(session.xfer.buflen == 1,
2✔
1114
    "Expected session.xfer.buflen 1, got %lu",
1115
    (unsigned long) session.xfer.buflen);
1116
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
2✔
1117
    "Expected '%s', got '%.100s'", expected, buf);
1118
}
1119
END_TEST
1✔
1120

1121
START_TEST (data_xfer_read_ascii_with_abor_test) {
1✔
1122
  int res;
1123
  char *buf, *expected;
1124
  size_t bufsz, expected_len;
1125
  cmd_rec *cmd;
1126

1127
  pr_data_clear_xfer_pool();
1✔
1128
  pr_data_reset();
1✔
1129

1130
  bufsz = 1024;
1✔
1131
  buf = palloc(p, bufsz);
1✔
1132

1133
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1134
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1135

1136
  /* read ASCII data */
1137
  session.xfer.direction = PR_NETIO_IO_RD;
1✔
1138
  session.xfer.p = make_sub_pool(p);
1✔
1139
  session.xfer.bufsize = 1024;
1✔
1140

1141
  /* Note: this string comes from the data_read_cb() we register with our
1142
   * DATA stream callback.
1143
   */
1144
  expected = "Hello,\n World!\n";
1✔
1145
  expected_len = strlen(expected);
1✔
1146

1147
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
1148
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
1149
    strerror(errno));
1150

1151
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1152
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
1153

1154
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
1155
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
1156
    strerror(errno));
1157

1158
  mark_point();
1✔
1159
  pr_ascii_ftp_reset();
1✔
1160
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1161
  session.xfer.buflen = 0;
1✔
1162

1163
  mark_point();
1✔
1164

1165
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "abor"));
1✔
1166
  tests_stubs_set_next_cmd(cmd);
1✔
1167

1168
  pr_ascii_ftp_reset();
1✔
1169
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1170
  session.xfer.buflen = 0;
1✔
1171

1172
  session.sf_flags |= SF_ASCII;
1✔
1173
  res = pr_data_xfer(buf, bufsz);
1✔
1174
  session.sf_flags &= ~SF_ASCII;
1✔
1175

1176
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
2✔
1177
    (unsigned long) expected_len, res);
1178
  ck_assert_msg(session.xfer.buflen == 0,
2✔
1179
    "Expected session.xfer.buflen 0, got %lu",
1180
    (unsigned long) session.xfer.buflen);
1181
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
2✔
1182
    "Expected '%s', got '%.100s'", expected, buf);
1183
}
1184
END_TEST
1✔
1185

1186
START_TEST (data_xfer_write_ascii_test) {
1✔
1187
  int res;
1188
  char *buf, *ascii_buf;
1189
  size_t buflen, ascii_buflen;
1190
  cmd_rec *cmd;
1191

1192
  pr_data_clear_xfer_pool();
1✔
1193
  pr_data_reset();
1✔
1194

1195
  res = pr_data_xfer(NULL, 0);
1✔
1196
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1197
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1198
    strerror(errno), errno);
1199

1200
  buf = "Hello,\n World\n";
1✔
1201
  buflen = strlen(buf);
1✔
1202

1203
  ascii_buf = "Hello,\r\n World\r\n";
1✔
1204
  ascii_buflen = strlen(ascii_buf);
1✔
1205

1206
  res = pr_data_xfer(buf, 0);
1✔
1207
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
2✔
1208
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1209
    strerror(errno), errno);
1210

1211
  mark_point();
1✔
1212
  res = pr_data_xfer(buf, buflen);
1✔
1213
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
1214
  ck_assert_msg(errno == ECONNABORTED,
2✔
1215
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
1216
    strerror(errno), errno);
1217

1218
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1219
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
2✔
1220

1221
  /* write ASCII data */
1222
  session.xfer.direction = PR_NETIO_IO_WR;
1✔
1223
  session.xfer.p = make_sub_pool(p);
1✔
1224
  session.xfer.buflen = 1024;
1✔
1225
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1226

1227
  mark_point();
1✔
1228
  data_write_eagain = TRUE;
1✔
1229
  pr_ascii_ftp_reset();
1✔
1230
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1231
  res = pr_data_xfer(buf, buflen);
1✔
1232
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1233

1234
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
2✔
1235
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2✔
1236
    strerror(errno), errno);
1237

1238
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
1239
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
1240
    strerror(errno));
1241

1242
  mark_point();
1✔
1243
  pr_ascii_ftp_reset();
1✔
1244
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1245
  res = pr_data_xfer(buf, buflen);
1✔
1246
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1247

1248
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
1249
    (unsigned long) buflen, res);
1250

1251
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1252
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
1253

1254
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
1255
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
1256
    strerror(errno));
1257

1258
  mark_point();
1✔
1259
  pr_ascii_ftp_reset();
1✔
1260
  session.xfer.buflen = 1024;
1✔
1261
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1262

1263
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1264
  res = pr_data_xfer(buf, buflen);
1✔
1265
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1266

1267
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
1268
    (unsigned long) buflen, res);
1269
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
2✔
1270
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1271
    (unsigned long) session.xfer.buflen);
1272

1273
  mark_point();
1✔
1274
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "noop"));
1✔
1275
  tests_stubs_set_next_cmd(cmd);
1✔
1276
  pr_ascii_ftp_reset();
1✔
1277
  session.xfer.buflen = 1024;
1✔
1278
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1279

1280
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1281
  res = pr_data_xfer(buf, buflen);
1✔
1282
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1283

1284
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
1285
    (unsigned long) buflen, res);
1286
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
2✔
1287
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1288
    (unsigned long) session.xfer.buflen);
1289

1290
  session.xfer.p = make_sub_pool(p);
1✔
1291
  mark_point();
1✔
1292
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "pasv"));
1✔
1293
  tests_stubs_set_next_cmd(cmd);
1✔
1294
  pr_ascii_ftp_reset();
1✔
1295
  session.xfer.buflen = 1024;
1✔
1296
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1297

1298
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1299
  res = pr_data_xfer(buf, buflen);
1✔
1300
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1301

1302
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
1303
    (unsigned long) buflen, res);
1304
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
2✔
1305
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1306
    (unsigned long) session.xfer.buflen);
1307

1308
  mark_point();
1✔
1309
  pr_ascii_ftp_reset();
1✔
1310
  session.xfer.buflen = 1024;
1✔
1311
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1312

1313
  session.sf_flags |= SF_ASCII;
1✔
1314
  res = pr_data_xfer(buf, buflen);
1✔
1315
  session.sf_flags &= ~SF_ASCII;
1✔
1316

1317
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
1318
    (unsigned long) buflen, res);
1319
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
2✔
1320
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1321
    (unsigned long) session.xfer.buflen);
1322
}
1323
END_TEST
1✔
1324

1325
START_TEST (data_xfer_write_ascii_with_abor_test) {
1✔
1326
  int res;
1327
  char *buf, *ascii_buf;
1328
  size_t buflen, ascii_buflen;
1329
  cmd_rec *cmd;
1330

1331
  pr_data_clear_xfer_pool();
1✔
1332
  pr_data_reset();
1✔
1333

1334
  buf = "Hello,\n World\n";
1✔
1335
  buflen = strlen(buf);
1✔
1336

1337
  ascii_buf = "Hello,\r\n World\r\n";
1✔
1338
  ascii_buflen = strlen(ascii_buf);
1✔
1339

1340
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1341
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1342

1343
  /* write ASCII data */
1344
  session.xfer.direction = PR_NETIO_IO_WR;
1✔
1345
  session.xfer.p = make_sub_pool(p);
1✔
1346
  session.xfer.buflen = 1024;
1✔
1347
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1348

1349
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
1350
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
1351
    strerror(errno));
1352

1353
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1354
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
1355

1356
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
1357
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
1358
    strerror(errno));
1359

1360
  mark_point();
1✔
1361

1362
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "abor"));
1✔
1363
  tests_stubs_set_next_cmd(cmd);
1✔
1364

1365
  pr_ascii_ftp_reset();
1✔
1366
  session.xfer.buflen = 1024;
1✔
1367
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1368

1369
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1370
  res = pr_data_xfer(buf, buflen);
1✔
1371
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1372

1373
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
2✔
1374
    (unsigned long) buflen, res);
1375
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
2✔
1376
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1377
    (unsigned long) session.xfer.buflen);
1378
}
1379
END_TEST
1✔
1380

1381
START_TEST (data_xfer_peek_nonsocket_test) {
1✔
1382
  int fd, res, strm_fd;
1383
  char *buf, *expected;
1384
  size_t bufsz, expected_len;
1385

1386
  pr_data_clear_xfer_pool();
1✔
1387
  pr_data_reset();
1✔
1388

1389
  mark_point();
1✔
1390
  bufsz = 1024;
1✔
1391
  buf = palloc(p, bufsz);
1✔
1392
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1393
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1394

1395
  /* read binary data */
1396
  session.xfer.direction = PR_NETIO_IO_RD;
1✔
1397

1398
  /* Note: this string comes from the data_read_cb() we register with our
1399
   * DATA stream callback.
1400
   */
1401
  expected = "Hello,\r\n World!\r\n";
1✔
1402
  expected_len = strlen(expected);
1✔
1403

1404
  session.xfer.buf = NULL;
1✔
1405
  session.xfer.buflen = 0;
1✔
1406

1407
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1✔
1408
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
2✔
1409
    strerror(errno));
1410

1411
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1412
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
2✔
1413

1414
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1✔
1415
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
2✔
1416
    strerror(errno));
1417

1418
  fd = tmpfile_fd();
1✔
1419
  if (fd < 0) {
1✔
1420
    return;
1421
  }
1422

1423
  strm_fd = PR_NETIO_FD(session.c->instrm);
1✔
1424
  PR_NETIO_FD(session.c->instrm) = fd;
1✔
1425

1426
  (void) write(fd, "FOO\r\n", 5);
1✔
1427
  rewind_fd(fd);
1✔
1428

1429
  mark_point();
1✔
1430
  session.xfer.buf = NULL;
1✔
1431
  session.xfer.buflen = 0;
1✔
1432
  data_write_eagain = TRUE;
1✔
1433

1434
  res = pr_data_xfer(buf, bufsz);
1✔
1435
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1✔
1436
    (unsigned long) expected_len, res);
1437
  ck_assert_msg(session.xfer.buflen == 0,
2✔
1438
    "Expected session.xfer.buflen 0, got %lu",
1439
    (unsigned long) session.xfer.buflen);
1440

1441
  (void) close(fd);
1✔
1442

1443
  PR_NETIO_FD(session.c->instrm) = strm_fd;
1✔
1444
  (void) pr_inet_close(p, session.c);
1✔
1445
  session.c = NULL;
1✔
1446
  if (session.d != NULL) {
1✔
1447
    (void) pr_inet_close(p, session.d);
1✔
1448
    session.d = NULL;
1✔
1449
  }
1450
}
1451
END_TEST
1452

1453
Suite *tests_get_data_suite(void) {
916✔
1454
  Suite *suite;
1455
  TCase *testcase;
1456

1457
  suite = suite_create("data");
916✔
1458

1459
  testcase = tcase_create("base");
916✔
1460
  tcase_add_checked_fixture(testcase, set_up, tear_down);
916✔
1461

1462
  tcase_add_test(testcase, data_get_timeout_test);
916✔
1463
  tcase_add_test(testcase, data_set_timeout_test);
916✔
1464
  tcase_add_test(testcase, data_ignore_ascii_test);
916✔
1465
  tcase_add_test(testcase, data_sendfile_test);
916✔
1466

1467
  tcase_add_test(testcase, data_init_test);
916✔
1468
  tcase_add_test(testcase, data_open_active_test);
916✔
1469
  tcase_add_test(testcase, data_open_active_rootrevoke_test);
916✔
1470
  tcase_add_test(testcase, data_open_passive_test);
916✔
1471
  tcase_add_test(testcase, data_close_test);
916✔
1472
  tcase_add_test(testcase, data_abort_test);
916✔
1473
  tcase_add_test(testcase, data_reset_test);
916✔
1474
  tcase_add_test(testcase, data_cleanup_test);
916✔
1475
  tcase_add_test(testcase, data_clear_xfer_pool_test);
916✔
1476
  tcase_add_test(testcase, data_xfer_read_binary_test);
916✔
1477
  tcase_add_test(testcase, data_xfer_write_binary_test);
916✔
1478
  tcase_add_test(testcase, data_xfer_read_ascii_test);
916✔
1479
  tcase_add_test(testcase, data_xfer_read_ascii_with_abor_test);
916✔
1480
  tcase_add_test(testcase, data_xfer_write_ascii_test);
916✔
1481
  tcase_add_test(testcase, data_xfer_write_ascii_with_abor_test);
916✔
1482
  tcase_add_test(testcase, data_xfer_peek_nonsocket_test);
916✔
1483

1484
  /* Allow a longer timeout on these tests, as they will need a second or
1485
   * two to actually run through the test itself, plus overhead.
1486
   */
1487
  tcase_set_timeout(testcase, 5);
916✔
1488

1489
  suite_add_tcase(suite, testcase);
916✔
1490
  return suite;
916✔
1491
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc