/* * 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; }
/*! Remove dpid_comm_keys file. * This avoids that dillo instances connect to a stale port after dpid * has exited (e.g. after a reboot). */ void cleanup() { char *fname; fname = dStrconcat(dGethomedir(), "/", dotDILLO_DPID_COMM_KEYS, NULL); unlink(fname); dFree(fname); }
/*! Register a service * Retrieves attributes for "service" and stores them * in dpi_attr. It looks for "service" in ~/.dillo/dpi * first, and then in the system wide dpi directory. * Caller must allocate memory for dpi_attr. * \Return * \li 0 on success * \li -1 on failure */ int register_service(struct dp *dpi_attr, char *service) { char *user_dpi_dir, *dpidrc, *user_service_dir, *dir = NULL; int ret = -1; user_dpi_dir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, NULL); user_service_dir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, "/", service, NULL); dpidrc = dStrconcat(dGethomedir(), "/", dotDILLO_DPIDRC, NULL); if (access(dpidrc, F_OK) == -1) { if (access(DPIDRC_SYS, F_OK) == -1) { ERRMSG("register_service", "Error ", 0); MSG_ERR("\n - There is no %s or %s file\n", dpidrc, DPIDRC_SYS); dFree(user_dpi_dir); dFree(user_service_dir); dFree(dpidrc); return(-1); } dFree(dpidrc); dpidrc = dStrdup(DPIDRC_SYS); } /* Check home dir for dpis */ if (access(user_service_dir, F_OK) == 0) { get_dpi_attr(user_dpi_dir, service, dpi_attr); ret = 0; } else { /* Check system wide dpis */ if ((dir = get_dpi_dir(dpidrc)) != NULL) { if (access(dir, F_OK) == 0) { get_dpi_attr(dir, service, dpi_attr); ret = 0; } else { ERRMSG("register_service", "get_dpi_attr failed", 0); } } else { ERRMSG("register_service", "dpi_dir: Error getting dpi dir.", 0); } } dFree(user_dpi_dir); dFree(user_service_dir); dFree(dpidrc); dFree(dir); return ret; }
/* * Initialize the cookies module * (The 'disabled' variable is writeable only within Cookies_init) */ static void Cookies_init() { char *filename; #ifndef HAVE_LOCKF struct flock lck; #endif struct tm future_tm = {7, 14, 3, 19, 0, 138, 0, 0, 0, 0, 0}; /* Default setting */ disabled = TRUE; cookies_epoch_time = mktime(&cookies_epoch_tm); cookies_future_time = mktime(&future_tm); /* Read and parse the cookie control file (cookiesrc) */ if (Cookie_control_init() != 0) { MSG("Disabling cookies.\n"); return; } /* Get a stream for the cookies file */ filename = dStrconcat(dGethomedir(), "/.dillo/cookies.txt", NULL); file_stream = Cookies_fopen(filename, "r+", cookies_txt_header_str); dFree(filename); if (!file_stream) { MSG("ERROR: Can't open ~/.dillo/cookies.txt; disabling cookies\n"); return; } /* Try to get a lock from the file descriptor */ #ifdef HAVE_LOCKF disabled = (lockf(fileno(file_stream), F_TLOCK, 0) == -1); #else /* POSIX lock */ lck.l_start = 0; /* start at beginning of file */ lck.l_len = 0; /* lock entire file */ lck.l_type = F_WRLCK; lck.l_whence = SEEK_SET; /* absolute offset */ disabled = (fcntl(fileno(file_stream), F_SETLK, &lck) == -1); #endif if (disabled) { MSG("The cookies file has a file lock; disabling cookies!\n"); fclose(file_stream); return; } MSG("Enabling cookies as per cookiesrc...\n"); Cookies_load_cookies(file_stream); }
/* * 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; }
/*! 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; }
/* * 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; }
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; } }
/*! Add services reading a dpidrc file * each non empty or commented line has the form * service = path_relative_to_dpidir * \Return: * \li Returns number of available services on success * \li -1 on failure */ int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list) { FILE *dpidrc_stream; char *p, *line = NULL, *service, *path; int i, st; struct service *s; char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL; user_dpidir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, NULL); if (access(user_dpidir, F_OK) == -1) { /* no dpis in user's space */ dFree(user_dpidir); user_dpidir = NULL; } dpidrc = dStrconcat(dGethomedir(), "/", dotDILLO_DPIDRC, NULL); if (access(dpidrc, F_OK) == -1) { dFree(dpidrc); dpidrc = dStrdup(DPIDRC_SYS); if (access(dpidrc, F_OK) == -1) { dFree(dpidrc); dpidrc = NULL; } } if (!dpidrc || (sys_dpidir = get_dpi_dir(dpidrc)) == NULL) sys_dpidir = NULL; if (!user_dpidir && !sys_dpidir) { ERRMSG("fill_services_list", "Fatal error ", 0); MSG_ERR("\n - Can't find the directory for dpis.\n"); exit(1); } if ((dpidrc_stream = fopen(dpidrc, "r")) == NULL) { ERRMSG("fill_services_list", "popen failed", errno); dFree(dpidrc); dFree(sys_dpidir); dFree(user_dpidir); return (-1); } if (*services_list != NULL) { ERRMSG("fill_services_list", "services_list parameter is not NULL", 0); return -1; } *services_list = dList_new(8); /* dpidrc parser loop */ for (;(line = dGetline(dpidrc_stream)) != NULL; dFree(line)) { st = dParser_parse_rc_line(&line, &service, &path); if (st < 0) { MSG_ERR("dpid: Syntax error in %s: service=\"%s\" path=\"%s\"\n", dpidrc, service, path); continue; } else if (st != 0) { continue; } _MSG("dpid: service=%s, path=%s\n", service, path); /* ignore dpi_dir silently */ if (strcmp(service, "dpi_dir") == 0) continue; s = dNew(struct service, 1); /* init services list entry */ s->name = dStrdup(service); s->dp_index = -1; dList_append(*services_list, s); /* search the dpi for a service by its path */ for (i = 0; i < numdpis; i++) if ((p = strstr(attlist[i].path, path)) && *(p - 1) == '/' && strlen(p) == strlen(path)) break; /* if the dpi exist bind service and dpi */ if (i < numdpis) s->dp_index = i; } fclose(dpidrc_stream); dList_sort(*services_list, (dCompareFunc)services_alpha_comp); dFree(dpidrc); dFree(sys_dpidir); dFree(user_dpidir); return (dList_length(*services_list)); }
/*! * Create dpi directory for available * plugins and create plugin list. * \Return * \li Returns number of available plugins on success * \li -1 on failure */ int register_all(struct dp **attlist) { DIR *user_dir_stream, *sys_dir_stream; char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL; struct dirent *user_dirent, *sys_dirent; int st; int snum; size_t dp_sz = sizeof(struct dp); if (*attlist != NULL) { ERRMSG("register_all", "attlist parameter should be NULL", 0); return -1; } user_dpidir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, NULL); if (access(user_dpidir, F_OK) == -1) { /* no dpis in user's space */ dFree(user_dpidir); user_dpidir = NULL; } dpidrc = dStrconcat(dGethomedir(), "/", dotDILLO_DPIDRC, NULL); if (access(dpidrc, F_OK) == -1) { dFree(dpidrc); dpidrc = dStrdup(DPIDRC_SYS); if (access(dpidrc, F_OK) == -1) { dFree(dpidrc); dpidrc = NULL; } } if (!dpidrc || (sys_dpidir = get_dpi_dir(dpidrc)) == NULL) sys_dpidir = NULL; dFree(dpidrc); if (!user_dpidir && !sys_dpidir) { ERRMSG("register_all", "Fatal error ", 0); MSG_ERR("\n - Can't find the directory for dpis.\n"); exit(1); } /* Get list of services in user's .dillo/dpi directory */ snum = 0; if (user_dpidir && (user_dir_stream = opendir(user_dpidir)) != NULL) { while ((user_dirent = readdir(user_dir_stream)) != NULL) { if (user_dirent->d_name[0] == '.') continue; *attlist = (struct dp *) dRealloc(*attlist, (snum + 1) * dp_sz); st=get_dpi_attr(user_dpidir, user_dirent->d_name, &(*attlist)[snum]); if (st == 0) snum++; } closedir(user_dir_stream); } if (sys_dpidir && (sys_dir_stream = opendir(sys_dpidir)) != NULL) { /* if system service is not in user list then add it */ while ((sys_dirent = readdir(sys_dir_stream)) != NULL) { if (sys_dirent->d_name[0] == '.') continue; *attlist = (struct dp *) dRealloc(*attlist, (snum + 1) * dp_sz); st=get_dpi_attr(sys_dpidir, sys_dirent->d_name, &(*attlist)[snum]); if (st == 0) snum++; } closedir(sys_dir_stream); } dFree(sys_dpidir); dFree(user_dpidir); /* TODO: do we consider snum == 0 an error? * (if so, we should return -1 ) */ return (snum); }