From 77ddcc8128741bdd54c40c96f9eebf868b1cc5f7 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sat, 6 Jan 2007 14:55:53 -0500 Subject: [PATCH] The OPEN and SAVE commands, when provided with a key, will no longer base 64 encode them. The MD5 hash will be created from the rest of the protocol command argument. All command-line options have been moved to a configuration file stored in ~/.pwmdrc by default. Use -f to specify an alternate rcfile. Added a rcfile option 'cache_push' which takes a list of filenames separated by a comma, to add to the file cache upon startup. The password or key for each file will be read from stdin. Added example config file doc/pwmdrc. --- doc/Makefile.am | 1 + doc/pwmdrc | 30 ++++ src/commands.c | 134 ++++++------------ src/common.h | 5 + src/pwmd.c | 417 +++++++++++++++++++++++++++++++++++++++++++++++--------- src/pwmd.h | 2 +- 6 files changed, 424 insertions(+), 165 deletions(-) create mode 100644 doc/pwmdrc diff --git a/doc/Makefile.am b/doc/Makefile.am index d7d37abd..a785f280 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1 +1,2 @@ +EXTRA_DIST = pwmdrc dist_man1_MANS = pwmd.1 diff --git a/doc/pwmdrc b/doc/pwmdrc new file mode 100644 index 00000000..ac9d18c2 --- /dev/null +++ b/doc/pwmdrc @@ -0,0 +1,30 @@ +# +# Example configuration file. If a configuration file doesn't exist a new one +# will be created in ~/.pwmdrc with the program defaults. +# +[default] + +# Location of the listening socket. +socket_path=~/.pwmd/socket + +# Where files will be read and stored. +data_directory=~/.pwmd + +# Log file location. +log_path=~/.pwmd/.log + +# Set to true to enable logging to log_path. +enable_logging=false + +# File and key cache size. Must be in multiples of your systems PAGE_SIZE. The +# default below on a x86 Linux system is one page. +#cache_size=4096 + +# Try setting to true if you have resource allocation limits and are getting +# memory allocation failures. +disable_mlockall=false + +# Files, separated by commas, to add to the file cache upon startup. You will +# be prompted for the key for each file. The files are looked for in +# data_directory. +#cache_push=somefile, anotherfile diff --git a/src/commands.c b/src/commands.c index 1588cc75..02da9de5 100644 --- a/src/commands.c +++ b/src/commands.c @@ -38,25 +38,25 @@ #include "pwmd_error.h" #include "commands.h" -static gboolean encrypt_xml(struct client_s *client, void *key, gsize keysize, +static gboolean encrypt_xml(gcry_cipher_hd_t gh, void *key, gsize keysize, guchar *iv, void *outbuf, gsize outsize, void *inbuf, gsize insize) { - if ((gcryerrno = gcry_cipher_reset(client->gh))) { + if ((gcryerrno = gcry_cipher_reset(gh))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } - if ((gcryerrno = gcry_cipher_setiv(client->gh, iv, gcryblocksize))) { + if ((gcryerrno = gcry_cipher_setiv(gh, iv, gcryblocksize))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } - if ((gcryerrno = gcry_cipher_setkey(client->gh, key, keysize))) { + if ((gcryerrno = gcry_cipher_setkey(gh, key, keysize))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } - if ((gcryerrno = gcry_cipher_encrypt(client->gh, outbuf, outsize, inbuf, insize))) { + if ((gcryerrno = gcry_cipher_encrypt(gh, outbuf, outsize, inbuf, insize))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } @@ -64,25 +64,25 @@ static gboolean encrypt_xml(struct client_s *client, void *key, gsize keysize, return TRUE; } -static gboolean decrypt_xml(struct client_s *client, void *key, gsize keysize, +gboolean decrypt_xml(gcry_cipher_hd_t gh, void *key, gsize keysize, guchar *iv, void *outbuf, gsize outsize, void *inbuf, gsize insize) { - if ((gcryerrno = gcry_cipher_reset(client->gh))) { + if ((gcryerrno = gcry_cipher_reset(gh))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } - if ((gcryerrno = gcry_cipher_setiv(client->gh, iv, gcryblocksize))) { + if ((gcryerrno = gcry_cipher_setiv(gh, iv, gcryblocksize))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } - if ((gcryerrno = gcry_cipher_setkey(client->gh, key, keysize))) { + if ((gcryerrno = gcry_cipher_setkey(gh, key, keysize))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } - if ((gcryerrno = gcry_cipher_decrypt(client->gh, outbuf, outsize, inbuf, insize))) { + if ((gcryerrno = gcry_cipher_decrypt(gh, outbuf, outsize, inbuf, insize))) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); return FALSE; } @@ -121,69 +121,6 @@ static gboolean valid_filename(const gchar *filename) return TRUE; } -static gint cache_file_count() -{ - void *p; - gint n = 0; - glong len; - file_cache_t f; - - for (p = shm_data, len = 0; len <= cache_size;) { - memcpy(&f, p, sizeof(file_cache_t)); - - if (f.used == TRUE) - n++; - - p += sizeof(file_cache_t); - len += sizeof(file_cache_t); - - if (len + sizeof(file_cache_t) > cache_size) - break; - } - - return n; -} - -static gboolean cache_add_file(const guchar *md5file, const guchar *md5key) -{ - void *p; - file_cache_t f; - gint nfiles = cache_file_count(); - glong len; - - /* - * Make sure there is enough secure memory. - */ - if (!md5file || (nfiles + 1) * sizeof(file_cache_t) > cache_size) - return FALSE; - - /* - * Find the first available "slot". - */ - for (p = shm_data, len = 0; len <= cache_size;) { - memcpy(&f, p, sizeof(file_cache_t)); - - if (f.used == FALSE) { - memcpy(&f.filename, md5file, sizeof(f.filename)); - - if (md5key) - memcpy(&f.key, md5key, sizeof(f.key)); - - f.used = TRUE; - memcpy(p, &f, sizeof(file_cache_t)); - return TRUE; - } - - p += sizeof(file_cache_t); - len += sizeof(file_cache_t); - - if (len + sizeof(file_cache_t) > cache_size) - break; - } - - return FALSE; -} - static gboolean cache_update_key(const guchar *md5filename, const guchar *md5key) { void *p; @@ -256,6 +193,21 @@ static gboolean cache_get_key(const guchar *md5file, guchar *md5key) return FALSE; } +gint open_file(const gchar *filename, struct stat *st) +{ + gint fd; + + if ((fd = open(filename, O_RDONLY)) == -1) + return -1; + + if (stat(filename, st) == -1) { + close(fd); + return -1; + } + + return fd; +} + gboolean open_command(struct client_s *client, gchar **req) { gint fd; @@ -263,9 +215,7 @@ gboolean open_command(struct client_s *client, gchar **req) gchar *inbuf; const gchar *filename = req[0]; guchar *iv; - gsize klen; guchar md5key[16]; - guchar *keytmp; gint cached = 0; if (!filename || !*filename) { @@ -309,11 +259,6 @@ new_doc: } } - if ((fd = open(filename, O_RDONLY)) == -1) { - send_to_client(client, "ERR %03i %s: %s\n", EPWMD_ERROR, filename, strerror(errno)); - return FALSE; - } - if (cache_get_key(client->md5file, md5key) == TRUE) cached = 1; else { @@ -321,13 +266,15 @@ new_doc: * No key specified and no matching filename found in the cache. */ if (!req[1] || !*req[1]) { - close(fd); send_error(client, EPWMD_KEY); return FALSE; } } - stat(filename, &st); + if ((fd = open_file(filename, &st)) == -1) { + send_to_client(client, "ERR %03i %s: %s\n", EPWMD_ERROR, filename, strerror(errno)); + return FALSE; + } if (st.st_size == 0) goto new_doc; @@ -340,13 +287,11 @@ new_doc: again: if (!cached) { - keytmp = g_base64_decode(req[1], &klen); - gcry_md_hash_buffer(GCRY_MD_MD5, md5key, keytmp, klen); - memset(keytmp, 0, klen); - g_free(keytmp); + gcry_md_hash_buffer(GCRY_MD_MD5, md5key, req[1], strlen(req[1])); + memset(req[1], 0, strlen(req[1])); } - if (decrypt_xml(client, md5key, gcrykeysize, iv, inbuf + gcryblocksize, + if (decrypt_xml(client->gh, md5key, gcrykeysize, iv, inbuf + gcryblocksize, st.st_size - gcryblocksize, NULL, 0) == FALSE) { if (cached) { cached = 0; @@ -366,6 +311,7 @@ again: client->len = st.st_size - gcryblocksize; if (g_strncasecmp(client->xml, "", 21) != 0) { + memset(client->xml, 0, client->len); send_error(client, EPWMD_BADKEY); return FALSE; } @@ -408,7 +354,7 @@ static gboolean get_elements(struct client_s *client, xmlTextReaderPtr reader, return TRUE; } -gboolean save_command(struct client_s *client, const gchar *filename, gchar *b64key) +gboolean save_command(struct client_s *client, const gchar *filename, gchar *key) { xmlChar *xmlbuf; gint insize; @@ -418,10 +364,8 @@ gboolean save_command(struct client_s *client, const gchar *filename, gchar *b64 guchar *iv; gint update = 1; guchar md5key[16]; - guchar *keytmp; - guint klen; - if (!b64key || !*b64key) { + if (!key || !key) { if (cache_get_key(client->md5file, md5key) == FALSE) { send_error(client, EPWMD_KEY); return FALSE; @@ -430,10 +374,8 @@ gboolean save_command(struct client_s *client, const gchar *filename, gchar *b64 update = 0; } else { - keytmp = g_base64_decode(b64key, &klen); - gcry_md_hash_buffer(GCRY_MD_MD5, md5key, keytmp, klen); - memset(keytmp, 0, klen); - g_free(keytmp); + gcry_md_hash_buffer(GCRY_MD_MD5, md5key, key, strlen(key)); + memset(key, 0, strlen(key)); } xmlDocDumpFormatMemory(client->doc, &xmlbuf, &insize, 0); @@ -455,7 +397,7 @@ gboolean save_command(struct client_s *client, const gchar *filename, gchar *b64 iv = gcry_malloc(gcryblocksize); gcry_create_nonce(iv, gcryblocksize); - if (encrypt_xml(client, md5key, gcrykeysize, iv, outbuf, insize, inbuf, insize) + if (encrypt_xml(client->gh, md5key, gcrykeysize, iv, outbuf, insize, inbuf, insize) == FALSE) { gcry_free(iv); memset(inbuf, 0, insize); diff --git a/src/common.h b/src/common.h index 6edfdab8..f0f8f99b 100644 --- a/src/common.h +++ b/src/common.h @@ -49,5 +49,10 @@ void log_write(const gchar *fmt, ...); void send_to_client(struct client_s *client, const gchar *fmt, ...); void send_error(struct client_s *client, int pwmd_errno); gchar **split_input_line(gchar *str, gchar *delim, gint n); +gint cache_file_count(); +gboolean cache_add_file(const guchar *md5file, const guchar *md5key); +gboolean decrypt_xml(gcry_cipher_hd_t gh, void *key, gsize keysize, + guchar *iv, void *outbuf, gsize outsize, void *inbuf, gsize insize); +gint open_file(const gchar *filename, struct stat *st); #endif diff --git a/src/pwmd.c b/src/pwmd.c index 35082c60..67a23dc5 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include @@ -133,21 +134,11 @@ static void catchsig(gint sig) static void usage(gchar *pn) { g_printf( -#ifdef HAVE_MLOCKALL - "Usage: %s [-hv] [-l [-M] [-C ] [-d ] [-s ]\n" -#else - "Usage: %s [-hv] [-l [-C ] [-d ] [-s ]\n" -#endif - " -d directory where to store and retrieve data files\n" - " -s socket path\n" -#ifdef HAVE_MLOCKALL - " -M disable mlockall()\n" -#endif - " -C cache size (%li)\n" - " -l enable logging to the specified file\n" + "Usage: %s [-hv] [-f ]\n" + " -f load the specified rcfile (~/.pwmdrc)\n" " -v version\n" " -h this help text\n", - pn, page_size); + pn); exit(EXIT_SUCCESS); } @@ -477,6 +468,230 @@ static void doit(int fd) _exit(EXIT_SUCCESS); } +void set_rcfile_defaults(GKeyFile *kf, const gchar *filename) +{ + gchar buf[PATH_MAX]; + gchar *new; + gsize len; + + snprintf(buf, sizeof(buf), "~/.pwmd/socket"); + g_key_file_set_string(kf, "default", "socket_path", buf); + snprintf(buf, sizeof(buf), "~/.pwmd"); + g_key_file_set_string(kf, "default", "data_directory", buf); + snprintf(buf, sizeof(buf), "~/.pwmd/.log"); + g_key_file_set_string(kf, "default", "log_path", buf); + g_key_file_set_boolean(kf, "default", "enable_logging", FALSE); + g_key_file_set_integer(kf, "default", "cache_size", cache_size); + g_key_file_set_boolean(kf, "default", "disable_mlockall", FALSE); + + new = g_key_file_to_data(kf, &len, NULL); + g_file_set_contents(filename, new, len, NULL); + g_free(new); +} + +GKeyFile *parse_rcfile(const gchar *filename) +{ + GKeyFile *kf = g_key_file_new(); + GError *error; + + if (g_key_file_load_from_file(kf, filename, G_KEY_FILE_NONE, &error) == FALSE) { + if (error->code == G_FILE_ERROR_NOENT) { + g_clear_error(&error); + set_rcfile_defaults(kf, filename); + return kf; + } + else { + warnx("%s: %s", filename, error->message); + g_clear_error(&error); + return NULL; + } + } + + return kf; +} + +static gboolean try_xml_decrypt(gint fd, struct stat st, guchar *key, gchar **xml, + gsize *len) +{ + guchar *iv; + gchar *inbuf; + gcry_cipher_hd_t gh; + + if ((gcryerrno = gcry_cipher_open(&gh, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0))) { + warnx("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(gcryerrno)); + return FALSE; + } + + inbuf = gcry_malloc(st.st_size); + read(fd, inbuf, st.st_size); + close(fd); + iv = gcry_malloc(gcryblocksize); + memcpy(iv, inbuf, gcryblocksize); + + if (decrypt_xml(gh, key, gcrykeysize, iv, inbuf + gcryblocksize, + st.st_size - gcryblocksize, NULL, 0) == FALSE) { + memset(inbuf, 0, st.st_size); + gcry_free(inbuf); + gcry_free(iv); + return FALSE; + } + + gcry_free(iv); + memmove(inbuf, inbuf + gcryblocksize, st.st_size - gcryblocksize); + *xml = inbuf; + *len = st.st_size - gcryblocksize; + + if (g_strncasecmp(*xml, "", 21) != 0) + return FALSE; + + return TRUE; +} + +static gboolean get_input(const gchar *filename, guchar *key) +{ + gchar buf[LINE_MAX], *p; + struct termios told, tnew; + gchar *xml = NULL; + gsize len = 0; + gint fd; + struct stat st; + int try = 0; + gint tty = isatty(STDIN_FILENO); + + if ((fd = open_file(filename, &st)) == -1) + return FALSE; + + if (st.st_size == 0) { + fprintf(stderr, "Skipping empty file '%s'.\n", filename); + close(fd); + return FALSE; + } + + if (tty) { + if (tcgetattr(STDIN_FILENO, &told) == -1) + err(EXIT_FAILURE, "tcgetattr()"); + + memcpy(&tnew, &told, sizeof(struct termios)); + tnew.c_lflag &= ~(ECHO); + tnew.c_lflag |= ICANON|ECHONL; + } + +again: + if (tty) { + if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) { + tcsetattr(STDIN_FILENO, TCSANOW, &told); + err(EXIT_FAILURE, "tcsetattr()"); + } + } + + printf("Password for '%s': ", filename); + + if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) { + if (tty) + tcsetattr(STDIN_FILENO, TCSANOW, &told); + + close(fd); + return FALSE; + } + + if (tty) + tcsetattr(STDIN_FILENO, TCSANOW, &told); + + p[strlen(p) - 1] = 0; + + if (!*p) { + fprintf(stderr, "Skipping.\n"); + close(fd); + return FALSE; + } + + gcry_md_hash_buffer(GCRY_MD_MD5, key, p, strlen(p)); + memset(buf, 0, sizeof(buf)); + + if (try_xml_decrypt(fd, st, key, &xml, &len) == FALSE) { + if (xml) { + memset(xml, 0, len); + g_free(xml); + } + + if (try++ == 2) { + fprintf(stderr, "Invalid password. Skipping file.\n"); + return FALSE; + } + else { + fprintf(stderr, "Invalid password.\n"); + goto again; + } + } + + memset(xml, 0, len); + g_free(xml); + return TRUE; +} + +gint cache_file_count() +{ + void *p; + gint n = 0; + glong len; + file_cache_t f; + + for (p = shm_data, len = 0; len <= cache_size;) { + memcpy(&f, p, sizeof(file_cache_t)); + + if (f.used == TRUE) + n++; + + p += sizeof(file_cache_t); + len += sizeof(file_cache_t); + + if (len + sizeof(file_cache_t) > cache_size) + break; + } + + return n; +} + +gboolean cache_add_file(const guchar *md5file, const guchar *md5key) +{ + void *p; + file_cache_t f; + gint nfiles = cache_file_count(); + glong len; + + /* + * Make sure there is enough secure memory. + */ + if (!md5file || (nfiles + 1) * sizeof(file_cache_t) > cache_size) + return FALSE; + + /* + * Find the first available "slot". + */ + for (p = shm_data, len = 0; len <= cache_size;) { + memcpy(&f, p, sizeof(file_cache_t)); + + if (f.used == FALSE) { + memcpy(&f.filename, md5file, sizeof(f.filename)); + + if (md5key) + memcpy(&f.key, md5key, sizeof(f.key)); + + f.used = TRUE; + memcpy(p, &f, sizeof(file_cache_t)); + return TRUE; + } + + p += sizeof(file_cache_t); + len += sizeof(file_cache_t); + + if (len + sizeof(file_cache_t) > cache_size) + break; + } + + return FALSE; +} + int main(int argc, char *argv[]) { gint opt; @@ -485,9 +700,13 @@ int main(int argc, char *argv[]) gchar buf[PATH_MAX]; gchar *socketpath = NULL, *socketdir, *socketname = NULL; gchar *socketarg = NULL; - gchar cwd[PATH_MAX]; gchar *datadir = NULL; gint fd; + GKeyFile *kf; + gboolean n; + gchar *p; + gchar **cache_push = NULL; + gchar *rcfile; #ifndef DEBUG #ifdef HAVE_SETRLIMIT struct rlimit rl; @@ -499,6 +718,8 @@ int main(int argc, char *argv[]) #endif #endif + rcfile = g_strdup_printf("%s/.pwmdrc", pw->pw_dir); + if ((page_size = sysconf(_SC_PAGESIZE)) == -1) err(EXIT_FAILURE, "sysconf()"); @@ -510,39 +731,14 @@ int main(int argc, char *argv[]) */ use_mlock = 1; - while ((opt = getopt(argc, argv, "C:Mhd:s:vl:")) != EOF) { + while ((opt = getopt(argc, argv, "hvf:")) != EOF) { #else - while ((opt = getopt(argc, argv, "C:hd:s:vl:")) != EOF) { + while ((opt = getopt(argc, argv, "hvf:")) != EOF) { #endif switch (opt) { - case 'l': - if (*optarg != '/') { - getcwd(buf, sizeof(buf)); - strncat(buf, "/", sizeof(buf)); - strncat(buf, optarg, sizeof(buf)); - logfile = g_strdup(buf); - } - else - logfile = g_strdup(optarg); - - break; - case 'C': - cache_size = strtol(optarg, NULL, 10); - - if (cache_size < page_size || cache_size % page_size || - (cache_size / page_size && cache_size % page_size)) - errx(EXIT_FAILURE, "cache size must be in multiples of %li.", page_size); - break; -#ifdef HAVE_MLOCKALL - case 'M': - use_mlock = 0; - break; -#endif - case 's': - socketarg = optarg; - break; - case 'd': - datadir = g_strdup(optarg); + case 'f': + g_free(rcfile); + rcfile = g_strdup(optarg); break; case 'v': printf("%s\n%s\n", PACKAGE_STRING, PACKAGE_BUGREPORT); @@ -553,40 +749,82 @@ int main(int argc, char *argv[]) } } - setup_gcrypt(); + if ((kf = parse_rcfile(rcfile)) == NULL) + exit(EXIT_FAILURE); - if (getcwd(cwd, sizeof(cwd)) == NULL) - err(EXIT_FAILURE, "getcwd()"); + g_key_file_set_list_separator(kf, ','); - if (datadir && !socketarg) { - socketdir = g_strdup_printf("%s/.pwmd", pw->pw_dir); - socketname = g_strdup("socket"); - socketpath = g_strdup_printf("%s/%s", socketdir, socketname); + if ((p = g_key_file_get_string(kf, "default", "socket_path", NULL)) == NULL) + errx(EXIT_FAILURE, "%s: socket_path not defined", rcfile); + + if (*p == '~') { + p++; + snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--); + g_free(p); + socketarg = g_strdup(buf); } + else + socketarg = p; - if (!datadir) { - snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir); + if ((p = g_key_file_get_string(kf, "default", "data_directory", NULL)) == NULL) + errx(EXIT_FAILURE, "%s: data_directory not defined", rcfile); + + if (*p == '~') { + p++; + snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--); + g_free(p); datadir = g_strdup(buf); } + else + datadir = p; + + if (g_key_file_has_key(kf, "default", "cache_size", NULL) == TRUE) { + cache_size = g_key_file_get_integer(kf, "default", "cache_size", NULL); + + if (cache_size < page_size || cache_size % page_size) + errx(EXIT_FAILURE, "cache size must be in multiples of %li.", page_size); + } + +#ifdef HAVE_MLOCKALL + if (g_key_file_has_key(kf, "default", "disable_mlockall", NULL) == TRUE) + use_mlock = g_key_file_get_integer(kf, "default", "disable_mlockall", NULL); +#endif + + if (g_key_file_has_key(kf, "default", "log_path", NULL) == TRUE) { + if (g_key_file_has_key(kf, "default", "enable_logging", NULL) == TRUE) { + n = g_key_file_get_boolean(kf, "default", "enable_logging", NULL); - if (!socketarg) { - socketdir = g_strdup_printf("%s/.pwmd", pw->pw_dir); - socketname = g_strdup("socket"); + if (n == TRUE) { + p = g_key_file_get_string(kf, "default", "log_path", NULL); + + if (*p == '~') { + p++; + snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--); + g_free(p); + logfile = g_strdup(buf); + } + else + logfile = p; + } + } + } + + if (g_key_file_has_key(kf, "default", "cache_push", NULL) == TRUE) + cache_push = g_key_file_get_string_list(kf, "default", "cache_push", NULL, NULL); + + g_key_file_free(kf); + + if (strchr(socketarg, '/') == NULL) { + socketdir = g_get_current_dir(); + socketname = g_strdup(socketarg); socketpath = g_strdup_printf("%s/%s", socketdir, socketname); } else { - if (strchr(socketarg, '/') == NULL) { - socketdir = g_strdup(cwd); - socketname = g_strdup(socketarg); - socketpath = g_strdup_printf("%s/%s", socketdir, socketname); - } - else { - socketname = g_strdup(strrchr(socketarg, '/')); - socketname++; - socketarg[strlen(socketarg) - strlen(socketname) -1] = 0; - socketdir = g_strdup(socketarg); - socketpath = g_strdup_printf("%s/%s", socketdir, socketname); - } + socketname = g_strdup(strrchr(socketarg, '/')); + socketname++; + socketarg[strlen(socketarg) - strlen(socketname) -1] = 0; + socketdir = g_strdup(socketarg); + socketpath = g_strdup_printf("%s/%s", socketdir, socketname); } snprintf(buf, sizeof(buf), "%s", datadir); @@ -640,6 +878,49 @@ int main(int argc, char *argv[]) } g_free(datadir); + setup_gcrypt(); + + /* + * Set the cache entry for a file. Prompts for the password. + */ + if (cache_push) { + guchar md5file[16]; + guchar key[16]; + + for (opt = 0; cache_push[opt]; opt++) { + p = cache_push[opt]; + + while (isspace(*p)) + p++; + + if (!*p) + continue; + + gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p)); + + if (access(p, R_OK|W_OK) != 0) { + if (errno != ENOENT) { + unlink(socketpath); + err(EXIT_FAILURE, "%s", p); + } + + warn("%s", p); + continue; + } + + if (get_input(p, key) == FALSE) + continue; + + if (cache_add_file(md5file, key) == FALSE) + errx(EXIT_FAILURE, "%s: couldn't add file (cache_size?)", p); + + fprintf(stderr, "Added.\n"); + memset(key, 0, sizeof(key)); + memset(md5file, 0, sizeof(md5file)); + } + + fprintf(stderr, "Done!\n"); + } if (listen(sfd, 0) == -1) err(EXIT_FAILURE, "listen()"); diff --git a/src/pwmd.h b/src/pwmd.h index 3237f8bb..290b0f88 100644 --- a/src/pwmd.h +++ b/src/pwmd.h @@ -37,7 +37,7 @@ static GMainLoop *gloop; static gint shm_fd; static glong page_size; #ifdef HAVE_MLOCKALL -static gint use_mlock; +static gboolean use_mlock; #endif static gchar *logfile; -- 2.11.4.GIT