aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2003-09-26 18:27:35 +0000
committerNick Mathewson <nickm@torproject.org>2003-09-26 18:27:35 +0000
commit92acbe12bc9512100b9282d7e9d61fe86b5a60bb (patch)
tree80cd3c92c91f30818c60a97842a1f106a8cb27ac /src/common
parent9e5cafc395397426030e8098d64b8e25625863c5 (diff)
downloadtor-92acbe12bc9512100b9282d7e9d61fe86b5a60bb.tar.gz
tor-92acbe12bc9512100b9282d7e9d61fe86b5a60bb.zip
Refactor common file code into util.c; add published to descriptors
svn:r487
Diffstat (limited to 'src/common')
-rw-r--r--src/common/crypto.c22
-rw-r--r--src/common/crypto.h1
-rw-r--r--src/common/util.c117
-rw-r--r--src/common/util.h12
4 files changed, 151 insertions, 1 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c
index b2ddbb1735..f6c7360d53 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -472,6 +472,28 @@ int crypto_pk_read_public_key_from_string(crypto_pk_env_t *env, char *src, int l
return 0;
}
+int
+crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
+ const char *fname)
+{
+ BIO *bio;
+ char *cp;
+ long len;
+ int r;
+ assert(env->type == CRYPTO_PK_RSA);
+ if (!(bio = BIO_new(BIO_s_mem())))
+ return -1;
+ if (PEM_write_bio_RSAPrivateKey(bio, (RSA*)env->key, NULL,NULL,0,0,NULL)) {
+ BIO_free(bio);
+ return -1;
+ }
+ len = BIO_get_mem_data(bio, &cp);
+ assert(len == strlen(cp));
+ r = write_str_to_file(fname, cp);
+ BIO_free(bio);
+ return r;
+}
+
int crypto_pk_write_private_key_to_file(crypto_pk_env_t *env, FILE *dest)
{
assert(env && dest);
diff --git a/src/common/crypto.h b/src/common/crypto.h
index ccd48fa56a..79e2447766 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -40,6 +40,7 @@ int crypto_pk_read_public_key_from_file(crypto_pk_env_t *env, FILE *src);
int crypto_pk_write_public_key_to_string(crypto_pk_env_t *env, char **dest, int *len);
int crypto_pk_read_public_key_from_string(crypto_pk_env_t *env, char *src, int len);
int crypto_pk_write_private_key_to_file(crypto_pk_env_t *env, FILE *dest);
+int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env, const char *fname);
int crypto_pk_write_public_key_to_file(crypto_pk_env_t *env, FILE *dest);
int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_read_private_key_from_filename(crypto_pk_env_t *env, const char *keyfile);
diff --git a/src/common/util.c b/src/common/util.c
index c942c5d731..a7a35acc94 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -13,6 +13,10 @@
#include "util.h"
#include "log.h"
+/*
+ * Memory
+ */
+
void *tor_malloc(size_t size) {
void *result;
@@ -26,6 +30,10 @@ void *tor_malloc(size_t size) {
return result;
}
+/*
+ * Time
+ */
+
void
my_gettimeofday(struct timeval *timeval)
{
@@ -88,6 +96,10 @@ void tv_addms(struct timeval *a, long ms) {
a->tv_usec %= 1000000;
}
+/*
+ * Low-level I/O.
+ */
+
/* a wrapper for write(2) that makes sure to write all count bytes.
* Only use if fd is a blocking socket. */
int write_all(int fd, const void *buf, size_t count) {
@@ -129,6 +141,10 @@ void set_socket_nonblocking(int socket)
#endif
}
+/*
+ * Process control
+ */
+
int spawn_func(int (*func)(void *), void *data)
{
#ifdef MS_WINDOWS
@@ -164,7 +180,9 @@ void spawn_exit()
}
-/* Fake socket pair over TCP. Code adapted from perl 5.8.0's util.c */
+/*
+ * Windows compatibility.
+ */
int
tor_socketpair(int family, int type, int protocol, int fd[2])
{
@@ -276,3 +294,100 @@ int correct_socket_errno(int s)
return WSAEWOULDBLOCK;
}
#endif
+
+/*
+ * Filesystem operations.
+ */
+file_status_t file_status(const char *fname)
+{
+ struct stat st;
+ if (stat(fname, &st)) {
+ if (errno == ENOENT) {
+ return FN_NOENT;
+ }
+ return FN_ERROR;
+ }
+ if (st.st_mode & S_IFDIR)
+ return FN_DIR;
+ else if (st.st_mode & S_IFREG)
+ return FN_FILE;
+ else
+ return FN_ERROR;
+}
+
+int check_private_dir(const char *dirname, int create)
+{
+ struct stat st;
+ if (stat(dirname, &st)) {
+ if (errno != ENOENT) {
+ log(LOG_ERR, "Directory %s cannot be read: %s", dirname,
+ strerror(errno));
+ return -1;
+ }
+ if (!create) {
+ log(LOG_ERR, "Directory %s does not exist.", dirname);
+ return -1;
+ }
+ log(LOG_INFO, "Creating directory %s", dirname);
+ if (mkdir(dirname, 0700)) {
+ log(LOG_ERR, "Error creating directory %s: %s", dirname,
+ strerror(errno));
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ if (!(st.st_mode & S_IFDIR)) {
+ log(LOG_ERR, "%s is not a directory", dirname);
+ return -1;
+ }
+ if (st.st_uid != getuid()) {
+ log(LOG_ERR, "%s is not owned by this UID (%d)", dirname, getuid());
+ return -1;
+ }
+ if (st.st_mode & 0077) {
+ log(LOG_WARNING, "Fixing permissions on directory %s", dirname);
+ if (chmod(dirname, 0700)) {
+ log(LOG_ERR, "Could not chmod directory %s: %s", dirname,
+ strerror(errno));
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int
+write_str_to_file(const char *fname, const char *str)
+{
+ char tempname[1024];
+ int fd;
+ FILE *file;
+ if (strlen(fname) > 1000) {
+ log(LOG_ERR, "Filename %s is too long.", fname);
+ return -1;
+ }
+ strcpy(tempname,fname);
+ strcat(tempname,".tmp");
+ if ((fd = open(tempname, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
+ log(LOG_ERR, "Couldn't open %s for writing: %s", tempname,
+ strerror(errno));
+ return -1;
+ }
+ if (!(file = fdopen(fd, "w"))) {
+ log(LOG_ERR, "Couldn't fdopen %s for writing: %s", tempname,
+ strerror(errno));
+ close(fd); return -1;
+ }
+ if (fputs(str,file)) {
+ log(LOG_ERR, "Error writing to %s: %s", tempname, strerror(errno));
+ fclose(file); return -1;
+ }
+ fclose(file);
+ if (rename(tempname, fname)) {
+ log(LOG_ERR, "Error replacing %s: %s", fname, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/common/util.h b/src/common/util.h
index 94fcd512dd..c90175669f 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -56,6 +56,18 @@ int read_all(int fd, void *buf, size_t count);
void set_socket_nonblocking(int socket);
+typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR} file_status_t;
+
+/* Return FN_ERROR if filename can't be read, FN_NOENT if it doesn't
+ * exist, FN_FILE if it is a regular file, or FN_DIR if it's a
+ * directory. */
+file_status_t file_status(const char *filename);
+/* Check whether dirname exists and is private. If yes returns
+ * 0. Else returns -1.
+ */
+int check_private_dir(const char *dirname, int create);
+int write_str_to_file(const char *fname, const char *str);
+
/* Minimalist interface to run a void function in the background. On
unix calls fork, on win32 calls beginthread. Returns -1 on failure.
func should not return, but rather should call spawn_exit.