diff options
author | Nick Mathewson <nickm@torproject.org> | 2003-09-26 18:27:35 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2003-09-26 18:27:35 +0000 |
commit | 92acbe12bc9512100b9282d7e9d61fe86b5a60bb (patch) | |
tree | 80cd3c92c91f30818c60a97842a1f106a8cb27ac /src/common | |
parent | 9e5cafc395397426030e8098d64b8e25625863c5 (diff) | |
download | tor-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.c | 22 | ||||
-rw-r--r-- | src/common/crypto.h | 1 | ||||
-rw-r--r-- | src/common/util.c | 117 | ||||
-rw-r--r-- | src/common/util.h | 12 |
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. |