~ubuntu-branches/ubuntu/lucid/curl/lucid-security

« back to all changes in this revision

Viewing changes to lib/sendf.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2009-04-29 11:10:29 UTC
  • mfrom: (3.2.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090429111029-2j5eiyokfw2bw049
Tags: 7.19.4-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Drop build dependencies: stunnel, libdb4.6-dev, libssh2-1-dev
  - Add build-dependency on openssh-server
  - Drop libssh2-1-dev from libcurl4-openssl-dev's Depends.
  - Call automake-1.9 with --add-missing --copy --force
* drop debian/patches/security_CVE-2009-0037.patch 
  - this patch is part of 7.19.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: sendf.c,v 1.142 2008-05-09 11:27:55 mmarek Exp $
 
21
 * $Id: sendf.c,v 1.155 2009-01-07 19:39:35 danf Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
47
47
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
48
48
#include <curl/mprintf.h>
49
49
 
50
 
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
 
50
/* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */
 
51
#if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI))
51
52
#include "krb4.h"
52
53
#else
53
54
#define Curl_sec_send(a,b,c,d) -1
91
92
  struct curl_slist     *last;
92
93
  struct curl_slist     *new_item;
93
94
 
94
 
  new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
 
95
  new_item = malloc(sizeof(struct curl_slist));
95
96
  if(new_item) {
96
97
    char *dupdata = strdup(data);
97
98
    if(dupdata) {
227
228
  if(data && data->set.verbose) {
228
229
    va_list ap;
229
230
    size_t len;
230
 
    char print_buffer[1024 + 1];
 
231
    char print_buffer[2048 + 1];
231
232
    va_start(ap, fmt);
232
 
    vsnprintf(print_buffer, 1024, fmt, ap);
 
233
    vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
233
234
    va_end(ap);
234
235
    len = strlen(print_buffer);
235
236
    Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
356
357
  int num = (sockfd == conn->sock[SECONDARYSOCKET]);
357
358
 
358
359
  if(conn->ssl[num].state == ssl_connection_complete)
359
 
    /* only TRUE if SSL enabled */
360
360
    bytes_written = Curl_ssl_send(conn, num, mem, len);
361
 
#ifdef USE_LIBSSH2
362
 
  else if(conn->protocol & PROT_SCP)
 
361
  else if(Curl_ssh_enabled(conn, PROT_SCP))
363
362
    bytes_written = Curl_scp_send(conn, num, mem, len);
364
 
  else if(conn->protocol & PROT_SFTP)
 
363
  else if(Curl_ssh_enabled(conn, PROT_SFTP))
365
364
    bytes_written = Curl_sftp_send(conn, num, mem, len);
366
 
#endif /* !USE_LIBSSH2 */
367
365
  else if(conn->sec_complete)
368
 
    /* only TRUE if krb enabled */
369
366
    bytes_written = Curl_sec_send(conn, num, mem, len);
370
367
  else
371
368
    bytes_written = send_plain(conn, num, mem, len);
376
373
  return retcode;
377
374
}
378
375
 
 
376
/*
 
377
 * Curl_write_plain() is an internal write function that sends data to the
 
378
 * server using plain sockets only. Otherwise meant to have the exact same
 
379
 * proto as Curl_write()
 
380
 */
 
381
CURLcode Curl_write_plain(struct connectdata *conn,
 
382
                          curl_socket_t sockfd,
 
383
                          const void *mem,
 
384
                          size_t len,
 
385
                          ssize_t *written)
 
386
{
 
387
  ssize_t bytes_written;
 
388
  CURLcode retcode;
 
389
  int num = (sockfd == conn->sock[SECONDARYSOCKET]);
 
390
 
 
391
  bytes_written = send_plain(conn, num, mem, len);
 
392
 
 
393
  *written = bytes_written;
 
394
  retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
 
395
 
 
396
  return retcode;
 
397
}
 
398
 
379
399
static CURLcode pausewrite(struct SessionHandle *data,
380
400
                           int type, /* what type of data */
381
 
                           char *ptr,
 
401
                           const char *ptr,
382
402
                           size_t len)
383
403
{
384
404
  /* signalled to pause sending on this connection, but since we have data
406
426
}
407
427
 
408
428
 
409
 
/* client_write() sends data to the write callback(s)
 
429
/* Curl_client_write() sends data to the write callback(s)
410
430
 
411
431
   The bit pattern defines to what "streams" to write to. Body and/or header.
412
432
   The defines are in sendf.h of course.
 
433
 
 
434
   If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
 
435
   local character encoding.  This is a problem and should be changed in
 
436
   the future to leave the original data alone.
413
437
 */
414
438
CURLcode Curl_client_write(struct connectdata *conn,
415
439
                           int type,
419
443
  struct SessionHandle *data = conn->data;
420
444
  size_t wrote;
421
445
 
 
446
  if(0 == len)
 
447
    len = strlen(ptr);
 
448
 
422
449
  /* If reading is actually paused, we're forced to append this chunk of data
423
450
     to the already held data, but only if it is the same type as otherwise it
424
451
     can't work and it'll return error instead. */
429
456
      /* major internal confusion */
430
457
      return CURLE_RECV_ERROR;
431
458
 
 
459
    DEBUGASSERT(data->state.tempwrite);
 
460
 
432
461
    /* figure out the new size of the data to save */
433
462
    newlen = len + data->state.tempwritesize;
434
463
    /* allocate the new memory area */
435
 
    newptr = malloc(newlen);
 
464
    newptr = realloc(data->state.tempwrite, newlen);
436
465
    if(!newptr)
437
466
      return CURLE_OUT_OF_MEMORY;
438
 
    /* copy the previously held data to the new area */
439
 
    memcpy(newptr, data->state.tempwrite, data->state.tempwritesize);
440
467
    /* copy the new data to the end of the new area */
441
468
    memcpy(newptr + data->state.tempwritesize, ptr, len);
442
 
    /* free the old data */
443
 
    free(data->state.tempwrite);
444
469
    /* update the pointer and the size */
445
470
    data->state.tempwrite = newptr;
446
471
    data->state.tempwritesize = newlen;
448
473
    return CURLE_OK;
449
474
  }
450
475
 
451
 
  if(0 == len)
452
 
    len = strlen(ptr);
453
 
 
454
476
  if(type & CLIENTWRITE_BODY) {
455
477
    if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
456
478
#ifdef CURL_DOES_CONVERSIONS
513
535
  return CURLE_OK;
514
536
}
515
537
 
516
 
#ifndef MIN
517
 
#define MIN(a,b) ((a) < (b) ? (a) : (b))
 
538
int Curl_read_plain(curl_socket_t sockfd,
 
539
                         char *buf,
 
540
                         size_t bytesfromsocket,
 
541
                         ssize_t *n)
 
542
{
 
543
  ssize_t nread = sread(sockfd, buf, bytesfromsocket);
 
544
 
 
545
  if(-1 == nread) {
 
546
    int err = SOCKERRNO;
 
547
#ifdef USE_WINSOCK
 
548
    if(WSAEWOULDBLOCK == err)
 
549
#else
 
550
    if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
518
551
#endif
 
552
      return -1;
 
553
    else
 
554
      return CURLE_RECV_ERROR;
 
555
  }
 
556
 
 
557
  /* we only return number of bytes read when we return OK */
 
558
  *n = nread;
 
559
  return CURLE_OK;
 
560
}
519
561
 
520
562
/*
521
563
 * Internal read-from-socket function. This is meant to deal with plain
545
587
 
546
588
  /* If session can pipeline, check connection buffer  */
547
589
  if(pipelining) {
548
 
    size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
 
590
    size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos, sizerequested);
549
591
 
550
592
    /* Copy from our master buffer first if we have some unread data there*/
551
593
    if(bytestocopy > 0) {
558
600
    }
559
601
    /* If we come here, it means that there is no data to read from the buffer,
560
602
     * so we read from the socket */
561
 
    bytesfromsocket = MIN(sizerequested, BUFSIZE * sizeof (char));
 
603
    bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
562
604
    buffertofill = conn->master_buffer;
563
605
  }
564
606
  else {
565
 
    bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
 
607
    bytesfromsocket = CURLMIN((long)sizerequested, conn->data->set.buffer_size ?
566
608
                          conn->data->set.buffer_size : BUFSIZE);
567
609
    buffertofill = buf;
568
610
  }
574
616
      return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
575
617
    }
576
618
  }
577
 
#ifdef USE_LIBSSH2
578
 
  else if(conn->protocol & (PROT_SCP|PROT_SFTP)) {
 
619
  else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
579
620
    if(conn->protocol & PROT_SCP)
580
621
      nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
581
622
    else if(conn->protocol & PROT_SFTP)
586
627
      return -1;
587
628
#endif
588
629
    if(nread < 0)
589
 
      /* since it is negative and not EGAIN, it was a protocol-layer error */
 
630
      /* since it is negative and not EAGAIN, it was a protocol-layer error */
590
631
      return CURLE_RECV_ERROR;
591
632
  }
592
 
#endif /* !USE_LIBSSH2 */
593
633
  else {
594
634
    if(conn->sec_complete)
595
635
      nread = Curl_sec_read(conn, sockfd, buffertofill,
596
636
                            bytesfromsocket);
597
 
    else
598
 
      nread = sread(sockfd, buffertofill, bytesfromsocket);
599
 
 
600
 
    if(-1 == nread) {
601
 
      int err = SOCKERRNO;
602
 
#ifdef USE_WINSOCK
603
 
      if(WSAEWOULDBLOCK == err)
604
 
#else
605
 
      if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
606
 
#endif
607
 
        return -1;
 
637
    /* TODO: Need to handle EAGAIN here somehow, similar to how it
 
638
     * is done in Curl_read_plain, either right here or in Curl_sec_read
 
639
     * itself. */
 
640
    else {
 
641
      int ret = Curl_read_plain(sockfd, buffertofill, bytesfromsocket,
 
642
                                     &nread);
 
643
      if(ret)
 
644
        return ret;
608
645
    }
609
646
  }
610
 
 
611
647
  if(nread >= 0) {
612
648
    if(pipelining) {
613
649
      memcpy(buf, conn->master_buffer, nread);
625
661
static int showit(struct SessionHandle *data, curl_infotype type,
626
662
                  char *ptr, size_t size)
627
663
{
628
 
  static const char * const s_infotype[CURLINFO_END] = {
 
664
  static const char s_infotype[CURLINFO_END][3] = {
629
665
    "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
630
666
 
631
667
#ifdef CURL_DOES_CONVERSIONS