Ejemplo n.º 1
0
/*
 * Read dpid's communication keys from its saved file.
 * Return value: 1 on success, -1 on error.
 */
static int Dpi_read_comm_keys(int *port)
{
   FILE *In;
   char *fname, *rcline = NULL, *tail;
   int i, ret = -1;

   fname = dStrconcat(dGethomedir(), "/.dillo/dpid_comm_keys", NULL);
   if ((In = fopen(fname, "r")) == NULL) {
      MSG_ERR("[Dpi_read_comm_keys] %s\n", dStrerror(errno));
   } else if ((rcline = dGetline(In)) == NULL) {
      MSG_ERR("[Dpi_read_comm_keys] empty file: %s\n", fname);
   } else {
      *port = strtol(rcline, &tail, 10);
      for (i = 0; *tail && isxdigit(tail[i+1]); ++i)
         SharedKey[i] = tail[i+1];
      SharedKey[i] = 0;
      ret = 1;
   }
   if (In)
      fclose(In);
   dFree(rcline);
   dFree(fname);

   return ret;
}
Ejemplo n.º 2
0
/*
 * Read all the available data from a filedescriptor.
 * This is intended for short answers, i.e. when we know the server
 * will write it all before being preempted. For answers that may come
 * as an stream with delays, non-blocking is better.
 * Return value: read data, or NULL on error and no data.
 */
static char *Dpi_blocking_read(int fd)
{
   int st;
   const int buf_sz = 8*1024;
   char buf[buf_sz], *msg = NULL;
   Dstr *dstr = dStr_sized_new(buf_sz);

   do {
      st = read(fd, buf, buf_sz);
      if (st < 0) {
         if (errno == EINTR) {
            continue;
         } else {
            MSG_ERR("[Dpi_blocking_read] %s\n", dStrerror(errno));
            break;
         }
      } else if (st > 0) {
         dStr_append_l(dstr, buf, st);
      }
   } while (st == buf_sz);

   msg = (dstr->len > 0) ? dstr->str : NULL;
   dStr_free(dstr, (dstr->len > 0) ? FALSE : TRUE);
   return msg;
}
Ejemplo n.º 3
0
static void Http_connect_queued_sockets(HostConnection_t *hc)
{
   SocketData_t *sd;
   while (hc->active_connections < prefs.http_max_conns &&
          (sd = Http_socket_dequeue(&hc->queue))) {

      sd->flags &= ~HTTP_SOCKET_QUEUED;

      if (sd->flags & HTTP_SOCKET_TO_BE_FREED) {
          dFree(sd);
      } else if (a_Web_valid(sd->web)) {
         /* start connecting the socket */
         if (Http_connect_socket(sd->Info) < 0) {
            ChainLink *Info = sd->Info;
            MSG_BW(sd->web, 1, "ERROR: %s", dStrerror(sd->Err));
            a_Chain_bfcb(OpAbort, Info, NULL, "Both");
            Http_socket_free(VOIDP2INT(Info->LocalKey)); /* free sd */
            dFree(Info);
         } else {
            sd->connected_to = hc->host;
            hc->active_connections++;
         }
      }
   }
}
Ejemplo n.º 4
0
/*
 * Return a file pointer. If the file doesn't exist, try to create it,
 * with the optional 'init_str' as its content.
 */
static FILE *Cookies_fopen(const char *filename, const char *mode,
                           const char *init_str)
{
   FILE *F_in;
   int fd, rc;

   if ((F_in = fopen(filename, mode)) == NULL) {
      /* Create the file */
      fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
      if (fd != -1) {
         if (init_str) {
            rc = write(fd, init_str, strlen(init_str));
            if (rc == -1) {
               MSG("Cookies: Could not write initial string to file %s: %s\n",
                  filename, dStrerror(errno));
            }
         }
         close(fd);

         MSG("Created file: %s\n", filename);
         F_in = fopen(filename, mode);
      } else {
         MSG("Could not create file: %s!\n", filename);
      }
   }

   if (F_in) {
      /* set close on exec */
      fcntl(fileno(F_in), F_SETFD, FD_CLOEXEC | fcntl(fileno(F_in), F_GETFD));
   }

   return F_in;
}
Ejemplo n.º 5
0
/*
 * Start dpid.
 * Return: 0 starting now, 1 Error.
 */
static int Dpi_start_dpid(void)
{
   pid_t pid;
   int st_pipe[2], ret = 1;
   char *answer;

   /* create a pipe to track our child's status */
   if (pipe(st_pipe))
      return 1;

   pid = fork();
   if (pid == 0) {
      /* This is the child process.  Execute the command. */
      char *path1 = dStrconcat(dGethomedir(), "/.dillo/dpid", NULL);
      Dpi_close_fd(st_pipe[0]);
      if (execl(path1, "dpid", (char*)NULL) == -1) {
         dFree(path1);
         if (execlp("dpid", "dpid", (char*)NULL) == -1) {
            MSG("Dpi_start_dpid (child): %s\n", dStrerror(errno));
            if (Dpi_blocking_write(st_pipe[1], "ERROR", 5) == -1) {
               MSG("Dpi_start_dpid (child): can't write to pipe.\n");
            }
            Dpi_close_fd(st_pipe[1]);
            _exit (EXIT_FAILURE);
         }
      }
   } else if (pid < 0) {
      /* The fork failed.  Report failure.  */
      MSG("Dpi_start_dpid: %s\n", dStrerror(errno));
      /* close the unused pipe */
      Dpi_close_fd(st_pipe[0]);
      Dpi_close_fd(st_pipe[1]);

   } else {
      /* This is the parent process, check our child status... */
      Dpi_close_fd(st_pipe[1]);
      if ((answer = Dpi_blocking_read(st_pipe[0])) != NULL) {
         MSG("Dpi_start_dpid: can't start dpid\n");
         dFree(answer);
      } else {
         ret = 0;
      }
      Dpi_close_fd(st_pipe[0]);
   }

   return ret;
}
Ejemplo n.º 6
0
Archivo: dpip.c Proyecto: epitron/dillo
/*
 * Close this socket for reading and writing.
 * (flush pending data)
 */
void a_Dpip_dsh_close(Dsh *dsh)
{
   int st;

   /* flush internal buffer */
   a_Dpip_dsh_write(dsh, 1, "", 0);

   /* close fds */
   st = dClose(dsh->fd_in);
   if (st < 0)
      MSG_ERR("[a_Dpip_dsh_close] close: %s\n", dStrerror(errno));
   if (dsh->fd_out != dsh->fd_in) {
      st = dClose(dsh->fd_out);
      if (st < 0)
         MSG_ERR("[a_Dpip_dsh_close] close: %s\n", dStrerror(errno));
   }
}
Ejemplo n.º 7
0
/*
 * Close this socket for reading and writing.
 * (flush pending data)
 */
void a_Dpip_dsh_close(Dsh *dsh)
{
   int st;

   /* flush internal buffer */
   a_Dpip_dsh_write(dsh, 1, "", 0);

   /* close fds */
   while((st = close(dsh->fd_in)) < 0 && errno == EINTR) ;
   if (st < 0)
      MSG_ERR("[a_Dpip_dsh_close] close: %s\n", dStrerror(errno));
   if (dsh->fd_out != dsh->fd_in) {
      while((st = close(dsh->fd_out)) < 0 && errno == EINTR) ;
      if (st < 0)
         MSG_ERR("[a_Dpip_dsh_close] close: %s\n", dStrerror(errno));
   }
}
Ejemplo n.º 8
0
/*
 * Read raw data from the socket into our buffer in
 * either BLOCKING or NONBLOCKING mode.
 */
static void Dpip_dsh_read(Dsh *dsh, int blocking)
{
   char buf[RBUF_SZ];
   int req_mode, old_flags = 0, st, ret = -3, nb = !blocking;

   dReturn_if (dsh->status == DPIP_ERROR || dsh->status == DPIP_EOF);

   req_mode = (nb) ? DPIP_NONBLOCK : 0;
   if ((dsh->mode & DPIP_NONBLOCK) != req_mode) {
      /* change mode temporarily... */
      old_flags = fcntl(dsh->fd_in, F_GETFL);
      fcntl(dsh->fd_in, F_SETFL,
            (nb) ? O_NONBLOCK | old_flags : old_flags & ~O_NONBLOCK);
   }

   while (1) {
      st = read(dsh->fd_in, buf, RBUF_SZ);
      if (st < 0) {
         if (errno == EINTR) {
            continue;
         } else if (errno == EAGAIN) {
            dsh->status = DPIP_EAGAIN;
            ret = -1;
            break;
         } else {
            MSG_ERR("[Dpip_dsh_read] %s\n", dStrerror(errno));
            dsh->status = DPIP_ERROR;
            break;
         }
      } else if (st == 0) {
         dsh->status = DPIP_EOF;
         break;
      } else {
         /* append to buf */
         dStr_append_l(dsh->rdbuf, buf, st);
         if (blocking)
            break;
      }
   }

   if ((dsh->mode & DPIP_NONBLOCK) != req_mode) {
      /* restore old mode */
      fcntl(dsh->fd_out, F_SETFL, old_flags);
   }

   /* assert there's no more data in the wire...
    * (st < buf upon interrupt || st == buf and no more data) */
   if (blocking)
      Dpip_dsh_read(dsh, 0);
}
Ejemplo n.º 9
0
static int Dpi_check_dpid_ids()
{
   struct sockaddr_in sin;
   const socklen_t sin_sz = sizeof(sin);
   int sock_fd, dpid_port, ret = -1;

   /* socket connection test */
   memset(&sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

   if (Dpi_read_comm_keys(&dpid_port) != -1) {
      sin.sin_port = htons(dpid_port);
      if ((sock_fd = Dpi_make_socket_fd()) == -1) {
         MSG("Dpi_check_dpid_ids: sock_fd=%d %s\n", sock_fd, dStrerror(errno));
      } else if (connect(sock_fd, (struct sockaddr *)&sin, sin_sz) == -1) {
         MSG("Dpi_check_dpid_ids: %s\n", dStrerror(errno));
      } else {
         Dpi_close_fd(sock_fd);
         ret = 1;
      }
   }
   return ret;
}
Ejemplo n.º 10
0
static int Dpi_blocking_write(int fd, const char *msg, int msg_len)
{
   int st, sent = 0;

   while (sent < msg_len) {
      st = write(fd, msg + sent, msg_len - sent);
      if (st < 0) {
         if (errno == EINTR) {
            continue;
         } else {
            MSG_ERR("[Dpi_blocking_write] %s\n", dStrerror(errno));
            break;
         }
      }
      sent += st;
   }

   return (sent == msg_len) ? 1 : -1;
}
Ejemplo n.º 11
0
Archivo: dpid.c Proyecto: epitron/dillo
/*! Save the current port and a shared secret in a file so dillo can find it.
 * \Return:
 * \li -1 on failure
 */
int save_comm_keys(int srs_port)
{
   int fd, ret = -1;
   char *fname, port_str[32];

   fname = dStrconcat(dGethomedir(), "/", dotDILLO_DPID_COMM_KEYS, NULL);
   fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
   dFree(fname);
   if (fd == -1) {
      MSG("save_comm_keys: open %s\n", dStrerror(errno));
   } else {
      snprintf(port_str, 16, "%d %s\n", srs_port, SharedKey);
      if (CKD_WRITE(fd, port_str) != -1 && CKD_CLOSE(fd) != -1) {
         ret = 1;
      }
   }

   return ret;
}
Ejemplo n.º 12
0
Archivo: dpip.c Proyecto: epitron/dillo
/*
 * Return value: 1..DataSize sent, -1 eagain, or -3 on big Error
 */
static int Dpip_dsh_write(Dsh *dsh, int nb, const char *Data, int DataSize)
{
   int req_mode, old_flags = 0, st, ret = -3, sent = 0;

   req_mode = (nb) ? DPIP_NONBLOCK : 0;
   if ((dsh->mode & DPIP_NONBLOCK) != req_mode) {
      /* change mode temporarily... */
      old_flags = fcntl(dsh->fd_out, F_GETFL);
      fcntl(dsh->fd_out, F_SETFL,
            (nb) ? O_NONBLOCK | old_flags : old_flags & ~O_NONBLOCK);
   }

   while (1) {
      st = write(dsh->fd_out, Data + sent, DataSize - sent);
      if (st < 0) {
         if (errno == EINTR) {
            continue;
         } else if (errno == EAGAIN) {
            dsh->status = DPIP_EAGAIN;
            ret = -1;
            break;
         } else {
            MSG_ERR("[Dpip_dsh_write] %s\n", dStrerror(errno));
            dsh->status = DPIP_ERROR;
            break;
         }
      } else {
         sent += st;
         if (nb || sent == DataSize) {
            ret = sent;
            break;
         }
      }
   }

   if ((dsh->mode & DPIP_NONBLOCK) != req_mode) {
      /* restore old mode */
      fcntl(dsh->fd_out, F_SETFL, old_flags);
   }

   return ret;
}
Ejemplo n.º 13
0
static int Dpi_connect_socket(const char *server_name)
{
   struct sockaddr_in sin;
   int sock_fd, dpi_port, ret = -1;
   char *cmd = NULL;

   /* Query dpid for the port number for this server */
   if ((dpi_port = Dpi_get_server_port(server_name)) == -1) {
      _MSG("Dpi_connect_socket:: can't get port number for %s\n", server_name);
      return -1;
   }
   _MSG("Dpi_connect_socket: server=%s port=%d\n", server_name, dpi_port);

   /* connect with this server's socket */
   memset(&sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
   sin.sin_port = htons(dpi_port);

   if ((sock_fd = Dpi_make_socket_fd()) == -1) {
      perror("[dpi::socket]");
   } else if (connect(sock_fd, (void*)&sin, sizeof(sin)) == -1) {
      MSG("[dpi::connect] errno:%d %s\n", errno, dStrerror(errno));

   /* send authentication Key (the server closes sock_fd on auth error) */
   } else if (!(cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "auth", SharedKey))) {
      MSG_ERR("[Dpi_connect_socket] Can't make auth message.\n");
   } else if (Dpi_blocking_write(sock_fd, cmd, strlen(cmd)) == -1) {
      MSG_ERR("[Dpi_connect_socket] Can't send auth message.\n");
   } else {
      ret = sock_fd;
   }
   dFree(cmd);
   if (sock_fd != -1 && ret == -1) /* can't send cmd? */
      Dpi_close_fd(sock_fd);

   return ret;
}
Ejemplo n.º 14
0
Archivo: dpip.c Proyecto: epitron/dillo
/*
 * Check whether the given 'auth' string equals what dpid saved.
 * Return value: 1 if equal, -1 otherwise
 */
int a_Dpip_check_auth(const char *auth_tag)
{
   char SharedSecret[32];
   FILE *In;
   char *fname, *rcline = NULL, *tail, *cmd, *msg;
   int i, port, ret = -1;

   /* sanity checks */
   if (!auth_tag ||
       !(cmd = a_Dpip_get_attr(auth_tag, "cmd")) || strcmp(cmd, "auth") ||
       !(msg = a_Dpip_get_attr(auth_tag, "msg"))) {
      return ret;
   }

   fname = dStrconcat(dGethomedir(), "/.dillo/dpid_comm_keys", NULL);
   if ((In = fopen(fname, "r")) == NULL) {
      MSG_ERR("[a_Dpip_check_auth] %s\n", dStrerror(errno));
   } else if ((rcline = dGetline(In)) == NULL) {
      MSG_ERR("[a_Dpip_check_auth] empty file: %s\n", fname);
   } else {
      port = strtol(rcline, &tail, 10);
      if (tail && port != 0) {
         for (i = 0; *tail && isxdigit(tail[i+1]); ++i)
            SharedSecret[i] = tail[i+1];
         SharedSecret[i] = 0;
         if (strcmp(msg, SharedSecret) == 0)
            ret = 1;
      }
   }
   if (In)
      fclose(In);
   dFree(rcline);
   dFree(fname);
   dFree(msg);
   dFree(cmd);

   return ret;
}
Ejemplo n.º 15
0
/*
 * This function gets called after the DNS succeeds solving a hostname.
 * Task: Finish socket setup and start connecting the socket.
 * Return value: 0 on success;  -1 on error.
 */
static int Http_connect_socket(ChainLink *Info)
{
   int i, status;
#ifdef ENABLE_IPV6
   struct sockaddr_in6 name;
#else
   struct sockaddr_in name;
#endif
   SocketData_t *S;
   DilloHost *dh;
   socklen_t socket_len = 0;

   S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey));

   /* TODO: iterate this address list until success, or end-of-list */
   for (i = 0; (dh = dList_nth_data(S->addr_list, i)); ++i) {
      if ((S->SockFD = socket(dh->af, SOCK_STREAM, IPPROTO_TCP)) < 0) {
         S->Err = errno;
         MSG("Http_connect_socket ERROR: %s\n", dStrerror(errno));
         continue;
      }
      /* set NONBLOCKING and close on exec. */
      fcntl(S->SockFD, F_SETFL, O_NONBLOCK | fcntl(S->SockFD, F_GETFL));
      fcntl(S->SockFD, F_SETFD, FD_CLOEXEC | fcntl(S->SockFD, F_GETFD));

      /* Some OSes require this...  */
      memset(&name, 0, sizeof(name));
      /* Set remaining parms. */
      switch (dh->af) {
      case AF_INET:
      {
         struct sockaddr_in *sin = (struct sockaddr_in *)&name;
         socket_len = sizeof(struct sockaddr_in);
         sin->sin_family = dh->af;
         sin->sin_port = S->port ? htons(S->port) : htons(DILLO_URL_HTTP_PORT);
         memcpy(&sin->sin_addr, dh->data, (size_t)dh->alen);
         if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl))
            MSG("Connecting to %s\n", inet_ntoa(sin->sin_addr));
         break;
      }
#ifdef ENABLE_IPV6
      case AF_INET6:
      {
         char buf[128];
         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&name;
         socket_len = sizeof(struct sockaddr_in6);
         sin6->sin6_family = dh->af;
         sin6->sin6_port =
            S->port ? htons(S->port) : htons(DILLO_URL_HTTP_PORT);
         memcpy(&sin6->sin6_addr, dh->data, dh->alen);
         inet_ntop(dh->af, dh->data, buf, sizeof(buf));
         if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl))
            MSG("Connecting to %s\n", buf);
         break;
      }
#endif
      }/*switch*/

      MSG_BW(S->web, 1, "Contacting host...");
      status = connect(S->SockFD, (struct sockaddr *)&name, socket_len);
      if (status == -1 && errno != EINPROGRESS) {
         S->Err = errno;
         Http_socket_close(S);
         MSG("Http_connect_socket ERROR: %s\n", dStrerror(S->Err));
      } else {
         a_Chain_bcb(OpSend, Info, &S->SockFD, "FD");
         a_Chain_fcb(OpSend, Info, &S->SockFD, "FD");
         Http_send_query(S->Info, S);
         return 0; /* Success */
      }
   }

   return -1;
}
Ejemplo n.º 16
0
/*
 * Return the dpi server's port number, or -1 on error.
 * (A query is sent to dpid and then its answer parsed)
 * note: as the available servers and/or the dpi socket directory can
 *       change at any time, we'll ask each time. If someday we find
 *       that connecting each time significantly degrades performance,
 *       an optimized approach can be tried.
 */
static int Dpi_get_server_port(const char *server_name)
{
   int sock_fd = -1, dpi_port = -1;
   int dpid_port, ok = 0;
   struct sockaddr_in sin;
   char *cmd, *request, *rply = NULL, *port_str;
   socklen_t sin_sz;

   dReturn_val_if_fail (server_name != NULL, dpi_port);
   _MSG("Dpi_get_server_port:: server_name = [%s]\n", server_name);

   /* Read dpid's port from saved file */
   if (Dpi_read_comm_keys(&dpid_port) != -1) {
      ok = 1;
   }
   if (ok) {
      /* Connect a socket with dpid */
      ok = 0;
      sin_sz = sizeof(sin);
      memset(&sin, 0, sizeof(sin));
      sin.sin_family = AF_INET;
      sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
      sin.sin_port = htons(dpid_port);
      if ((sock_fd = Dpi_make_socket_fd()) == -1 ||
          connect(sock_fd, (struct sockaddr *)&sin, sin_sz) == -1) {
         MSG("Dpi_get_server_port: %s\n", dStrerror(errno));
      } else {
         ok = 1;
      }
   }
   if (ok) {
      /* ask dpid to check the dpi and send its port number back */
      ok = 0;
      request = a_Dpip_build_cmd("cmd=%s msg=%s", "check_server", server_name);
      _MSG("[%s]\n", request);

      if (Dpi_blocking_write(sock_fd, request, strlen(request)) == -1) {
         MSG("Dpi_get_server_port: %s\n", dStrerror(errno));
      } else {
         ok = 1;
      }
      dFree(request);
   }
   if (ok) {
      /* Get the reply */
      ok = 0;
      if ((rply = Dpi_blocking_read(sock_fd)) == NULL) {
         MSG("Dpi_get_server_port: can't read server port from dpid.\n");
      } else {
         ok = 1;
      }
   }
   if (ok) {
      /* Parse reply */
      ok = 0;
      cmd = a_Dpip_get_attr(rply, "cmd");
      if (strcmp(cmd, "send_data") == 0) {
         port_str = a_Dpip_get_attr(rply, "msg");
         _MSG("Dpi_get_server_port: rply=%s\n", rply);
         _MSG("Dpi_get_server_port: port_str=%s\n", port_str);
         dpi_port = strtol(port_str, NULL, 10);
         dFree(port_str);
         ok = 1;
      }
      dFree(cmd);
   }
   dFree(rply);
   Dpi_close_fd(sock_fd);

   return ok ? dpi_port : -1;
}
Ejemplo n.º 17
0
/*
 * Flush cookies to disk and free all the memory allocated.
 */
static void Cookies_save_and_free()
{
   int i, fd, saved = 0;
   DomainNode *node;
   CookieData_t *cookie;
   time_t now;

#ifndef HAVE_LOCKF
   struct flock lck;
#endif

   if (disabled)
      return;

   now = time(NULL);

   rewind(file_stream);
   fd = fileno(file_stream);
   if (ftruncate(fd, 0) == -1)
      MSG("Cookies: Truncate file stream failed: %s\n", dStrerror(errno));
   fprintf(file_stream, "%s", cookies_txt_header_str);

   /* Iterate cookies per domain, saving and freeing */
   while ((node = dList_nth_data(domains, 0))) {
      for (i = 0; (cookie = dList_nth_data(node->cookies, i)); ++i) {
         if (!cookie->session_only && difftime(cookie->expires_at, now) > 0) {
            int len;
            char buf[LINE_MAXLEN];

            len = snprintf(buf, LINE_MAXLEN, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n",
                           cookie->domain,
                           cookie->host_only ? "FALSE" : "TRUE",
                           cookie->path,
                           cookie->secure ? "TRUE" : "FALSE",
                           (long) difftime(cookie->expires_at,
                                           cookies_epoch_time),
                           cookie->name,
                           cookie->value);
            if (len < LINE_MAXLEN) {
               fprintf(file_stream, "%s", buf);
               saved++;
            } else {
               MSG("Not saving overly long cookie for %s.\n", cookie->domain);
            }
         }
         Cookies_free_cookie(cookie);
      }
      Cookies_delete_node(node);
   }
   dList_free(domains);
   dList_free(all_cookies);

#ifdef HAVE_LOCKF
   lockf(fd, F_ULOCK, 0);
#else  /* POSIX file lock */
   lck.l_start = 0; /* start at beginning of file */
   lck.l_len = 0;  /* lock entire file */
   lck.l_type = F_UNLCK;
   lck.l_whence = SEEK_SET;  /* absolute offset */

   fcntl(fileno(file_stream), F_SETLKW, &lck);
#endif
   fclose(file_stream);

   MSG("Cookies saved: %d.\n", saved);
}
Ejemplo n.º 18
0
/*
 * Read in cookies from 'stream' (cookies.txt)
 */
static void Cookies_load_cookies(FILE *stream)
{
   char line[LINE_MAXLEN];

   all_cookies = dList_new(32);
   domains = dList_new(32);

   /* Get all lines in the file */
   while (!feof(stream)) {
      line[0] = '\0';
      if ((fgets(line, LINE_MAXLEN, stream) == NULL) && ferror(stream)) {
         MSG("Error while reading from cookies.txt: %s\n", dStrerror(errno));
         break; /* bail out */
      }

      /* Remove leading and trailing whitespaces */
      dStrstrip(line);

      if ((line[0] != '\0') && (line[0] != '#')) {
         /*
          * Split the row into pieces using a tab as the delimiter.
          * pieces[0] The domain name
          * pieces[1] TRUE/FALSE: is the domain a suffix, or a full domain?
          * pieces[2] The path
          * pieces[3] TRUE/FALSE: is the cookie for secure use only?
          * pieces[4] Timestamp of expire date
          * pieces[5] Name of the cookie
          * pieces[6] Value of the cookie
          */
         CookieControlAction action;
         char *piece;
         char *line_marker = line;
         CookieData_t *cookie = dNew0(CookieData_t, 1);

         cookie->session_only = FALSE;
         cookie->domain = dStrdup(dStrsep(&line_marker, "\t"));
         piece = dStrsep(&line_marker, "\t");
         if (piece != NULL && piece[0] == 'F')
            cookie->host_only = TRUE;
         cookie->path = dStrdup(dStrsep(&line_marker, "\t"));
         piece = dStrsep(&line_marker, "\t");
         if (piece != NULL && piece[0] == 'T')
            cookie->secure = TRUE;
         piece = dStrsep(&line_marker, "\t");
         if (piece != NULL) {
            /* There is some problem with simply putting the maximum value
             * into tm.tm_sec (although a value close to it works).
             */
            long seconds = strtol(piece, NULL, 10);
            struct tm tm;
            Cookies_tm_init(&tm);
            tm.tm_min += seconds / 60;
            tm.tm_sec += seconds % 60;
            cookie->expires_at = mktime(&tm);
         } else {
            cookie->expires_at = (time_t) -1;
         }
         cookie->name = dStrdup(dStrsep(&line_marker, "\t"));
         cookie->value = dStrdup(line_marker ? line_marker : "");

         if (!cookie->domain || cookie->domain[0] == '\0' ||
             !cookie->path || cookie->path[0] != '/' ||
             !cookie->name || !cookie->value) {
            MSG("Malformed line in cookies.txt file!\n");
            Cookies_free_cookie(cookie);
            continue;
         }

         action = Cookies_control_check_domain(cookie->domain);
         if (action == COOKIE_DENY) {
            Cookies_free_cookie(cookie);
            continue;
         } else if (action == COOKIE_ACCEPT_SESSION) {
            cookie->session_only = TRUE;
         }

         /* Save cookie in memory */
         Cookies_add_cookie(cookie);
      }
   }
   MSG("Cookies loaded: %d.\n", dList_length(all_cookies));
}
Ejemplo n.º 19
0
int Cookies_rc_check()
{
   const int line_maxlen = 4096;
   FILE *stream;
   char *filename;
   char line[line_maxlen];
   bool_t default_deny = TRUE;

   /* Get a file pointer */
   filename = dStrconcat(dGethomedir(), "/.dillo/cookiesrc", NULL);
   stream = fopen(filename, "r");
   dFree(filename);

   if (!stream) {
      MSG_ERR("Cannot run test; cannot open cookiesrc.\n");
      return 1;
   }

   /* Get all lines in the file */
   while (!feof(stream)) {
      char *rc;

      line[0] = '\0';
      rc = fgets(line, line_maxlen, stream);
      if (!rc && ferror(stream)) {
         MSG_ERR("Error while reading rule from cookiesrc: %s\n",
             dStrerror(errno));
         fclose(stream);
         return 2;
      }

      /* Remove leading and trailing whitespaces */
      dStrstrip(line);

      if (line[0] != '\0' && line[0] != '#') {
         int domain_end, i = 0;
         const char *rule;

         /* Get the domain */
         while (line[i] != '\0' && !dIsspace(line[i]))
            i++;
         domain_end = i;

         /* Skip past whitespace */
         while (dIsspace(line[i]))
            i++;
         line[domain_end] = '\0';

         /* Get the rule */
         rule = line + i;
         while (line[i] != '\0' && !dIsspace(line[i]))
            i++;
         line[i] = '\0';

         if (!dStrAsciiCasecmp(line, "DEFAULT")) {
            if (!dStrAsciiCasecmp(rule, "ACCEPT") ||
                !dStrAsciiCasecmp(rule, "ACCEPT_SESSION"))
               default_deny = FALSE;
         } else {
            if (!dStrAsciiCasecmp(rule, "DENY"))
               MSG_WARN("DENY rules in cookiesrc can interfere with test.\n");
         }
      }
   }
   fclose(stream);

   if (default_deny) {
      MSG_ERR("Cannot run test with cookiesrc default of deny.\n");
      return 1;
   } else {
      return 0;
   }
}