/* * 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; }
/* * 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; }
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++; } } } }
/* * 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; }
/* * 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; }
/* * 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)); } }
/* * 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)); } }
/* * 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); }
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; }
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; }
/*! 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; }
/* * 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; }
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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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); }
/* * 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)); }
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; } }