summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Federico Mena Quintero2013-07-02 13:38:36 -0500
committerGravatar Federico Mena Quintero2013-07-02 20:31:45 -0500
commita2ddca0916ef776dbd0c6304ea36b4ca7a35302c (patch)
treed744dbf3df01d57a6fea739181fa525d8ea2e97f
parent42892465d4522cf19283b8a06bf48104bb387430 (diff)
downloadlibimobiledevice-a2ddca0916ef776dbd0c6304ea36b4ca7a35302c.tar.gz
libimobiledevice-a2ddca0916ef776dbd0c6304ea36b4ca7a35302c.tar.bz2
Bug #331 - Don't create a /tmp/root directory insecurely
When finding the user's home directory to generate a subdirectory in $HOME/.config, we would fall back to /tmp if there were no environment variables for HOME or XDG_CONFIG_HOME. Since libimobiledevice gets used by upower, and since upowerd runs as root, this would cause a /tmp/root directory to be created insecurely, leaving upowerd vulnerable to a symlink attack. Now we fall back to getpwuid_r() to find the user's home directory if it is not provided in environment variables - this is the case when upowerd gets run via systemd, for example. The result is that we'll end up creating /root/.config, a safe directory, since regular users cannot create symlinks in /root. In the future we'll need a way for libimobiledevice to find where to store its pairing data on behalf of the console user, rather than writing it to /root. http://libiphone.lighthouseapp.com/projects/27916-libiphone/tickets/331-insecure-tmp-directory-use
-rw-r--r--common/userpref.c105
1 files changed, 76 insertions, 29 deletions
diff --git a/common/userpref.c b/common/userpref.c
index d363b0e..ab3a3cf 100644
--- a/common/userpref.c
+++ b/common/userpref.c
@@ -26,6 +26,9 @@
26#include <stdint.h> 26#include <stdint.h>
27#include <stdlib.h> 27#include <stdlib.h>
28#include <string.h> 28#include <string.h>
29#include <sys/types.h>
30#include <pwd.h>
31#include <unistd.h>
29#ifdef HAVE_OPENSSL 32#ifdef HAVE_OPENSSL
30#include <openssl/pem.h> 33#include <openssl/pem.h>
31#include <openssl/rsa.h> 34#include <openssl/rsa.h>
@@ -48,6 +51,7 @@
48 51
49#include "userpref.h" 52#include "userpref.h"
50#include "debug.h" 53#include "debug.h"
54#include "utils.h"
51 55
52#define LIBIMOBILEDEVICE_CONF_DIR "libimobiledevice" 56#define LIBIMOBILEDEVICE_CONF_DIR "libimobiledevice"
53#define LIBIMOBILEDEVICE_CONF_FILE "libimobiledevicerc" 57#define LIBIMOBILEDEVICE_CONF_FILE "libimobiledevicerc"
@@ -65,7 +69,7 @@
65#define DIR_SEP_S "/" 69#define DIR_SEP_S "/"
66#endif 70#endif
67 71
68static char __config_dir[512] = {0, }; 72static char *__config_dir = NULL;
69 73
70#ifdef WIN32 74#ifdef WIN32
71static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written) 75static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written)
@@ -103,24 +107,60 @@ static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read,
103#endif 107#endif
104 108
105#ifndef WIN32 109#ifndef WIN32
106static const char *userpref_get_tmp_dir() 110static char *get_home_dir_from_system(void)
107{ 111{
108 const char *cdir = getenv("TMPDIR"); 112 long bufsize;
109 if (cdir && cdir[0]) 113 char *buf;
110 return cdir; 114 int error;
111 cdir = getenv("TMP"); 115 struct passwd pwd;
112 if (cdir && cdir[0]) 116 struct passwd *ppwd;
113 return cdir; 117 char *result = NULL;
114 cdir = getenv("TEMP"); 118
115 if (cdir && cdir[0]) 119 bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
116 return cdir; 120
117 return "/tmp"; 121 if (bufsize < 0)
122 bufsize = 1024;
123
124 buf = NULL;
125
126 do {
127 free (buf);
128 buf = malloc (bufsize);
129 if (!buf)
130 return NULL;
131
132 errno = 0;
133 error = getpwuid_r (getuid (), &pwd, buf, bufsize, &ppwd);
134
135 error = (error < 0) ? errno : error;
136
137 if (!ppwd) {
138 if (error == 0 || error == ENOENT)
139 break;
140 else if (bufsize > 32 * 1024)
141 break; /* Unreasonable size; let's bail out */
142
143 bufsize *= 2;
144 }
145 } while (!ppwd);
146
147 if (ppwd && ppwd->pw_dir)
148 result = strdup (ppwd->pw_dir);
149
150 free (buf);
151
152 return result;
118} 153}
119#endif 154#endif
120 155
121static const char *userpref_get_config_dir() 156static const char *userpref_get_config_dir()
122{ 157{
123 if (__config_dir[0]) return __config_dir; 158 char *base_config_dir;
159 int use_dot_config;
160
161 if (__config_dir)
162 return __config_dir;
163
124#ifdef WIN32 164#ifdef WIN32
125 wchar_t path[MAX_PATH+1]; 165 wchar_t path[MAX_PATH+1];
126 HRESULT hr; 166 HRESULT hr;
@@ -131,38 +171,45 @@ static const char *userpref_get_config_dir()
131 if (hr == S_OK) { 171 if (hr == S_OK) {
132 b = SHGetPathFromIDListW (pidl, path); 172 b = SHGetPathFromIDListW (pidl, path);
133 if (b) { 173 if (b) {
134 char *cdir = userpref_utf16_to_utf8 (path, wcslen(path), NULL, NULL); 174 base_config_dir = userpref_utf16_to_utf8 (path, wcslen(path), NULL, NULL);
135 strcpy(__config_dir, cdir);
136 free(cdir);
137 CoTaskMemFree (pidl); 175 CoTaskMemFree (pidl);
138 } 176 }
139 } 177 }
178
179 use_dot_config = 0;
140#else 180#else
141 const char *cdir = getenv("XDG_CONFIG_HOME"); 181 const char *cdir = getenv("XDG_CONFIG_HOME");
142 if (!cdir) { 182 if (!cdir) {
143 cdir = getenv("HOME"); 183 cdir = getenv("HOME");
144 if (!cdir || !cdir[0]) { 184 if (!cdir || !cdir[0]) {
145 const char *tdir = userpref_get_tmp_dir(); 185 base_config_dir = get_home_dir_from_system();
146 strcpy(__config_dir, tdir); 186 if (!base_config_dir)
147 strcat(__config_dir, DIR_SEP_S); 187 return NULL;
148 strcat(__config_dir, "root");
149 } else { 188 } else {
150 strcpy(__config_dir, cdir); 189 base_config_dir = strdup(cdir);
151 } 190 }
152 strcat(__config_dir, DIR_SEP_S); 191
153 strcat(__config_dir, ".config"); 192 use_dot_config = 1;
154 } else { 193 } else {
155 strcpy(__config_dir, cdir); 194 base_config_dir = strdup(cdir);
195 use_dot_config = 0;
156 } 196 }
157#endif 197#endif
158 strcat(__config_dir, DIR_SEP_S);
159 strcat(__config_dir, LIBIMOBILEDEVICE_CONF_DIR);
160 198
161 int i = strlen(__config_dir)-1; 199 if (use_dot_config)
162 while ((i > 0) && (__config_dir[i] == DIR_SEP)) { 200 __config_dir = string_concat(base_config_dir, DIR_SEP_S, ".config", DIR_SEP_S, LIBIMOBILEDEVICE_CONF_DIR);
163 __config_dir[i--] = '\0'; 201 else
202 __config_dir = string_concat(base_config_dir, DIR_SEP_S, LIBIMOBILEDEVICE_CONF_DIR);
203
204 if (__config_dir) {
205 int i = strlen(__config_dir)-1;
206 while ((i > 0) && (__config_dir[i] == DIR_SEP)) {
207 __config_dir[i--] = '\0';
208 }
164 } 209 }
165 210
211 free(base_config_dir);
212
166 return __config_dir; 213 return __config_dir;
167} 214}
168 215