1 /**
2 * Author......: See docs/credits.txt
3 * License.....: MIT
4 */
5
6 #include "common.h"
7 #include "types.h"
8 #include "memory.h"
9 #include "event.h"
10 #include "shared.h"
11 #include "folder.h"
12 #include <libgen.h>
13
14 #if defined (__APPLE__)
15 #include "event.h"
16 #endif
17
get_exec_path(char * exec_path,const size_t exec_path_sz)18 static int get_exec_path (char *exec_path, const size_t exec_path_sz)
19 {
20 #if defined (__linux__) || defined (__CYGWIN__)
21
22 char *tmp;
23
24 hc_asprintf (&tmp, "/proc/%d/exe", getpid ());
25
26 const ssize_t len = readlink (tmp, exec_path, exec_path_sz - 1);
27
28 hcfree (tmp);
29
30 if (len == -1) return -1;
31
32 #elif defined (_WIN)
33
34 memset (exec_path, 0, exec_path_sz);
35
36 const int len = 0;
37
38 #elif defined (__APPLE__)
39
40 u32 size = (u32) exec_path_sz;
41
42 if (_NSGetExecutablePath (exec_path, &size) != 0) return -1;
43
44 const size_t len = strlen (exec_path);
45
46 #elif defined (__FreeBSD__) || defined(__DragonFly__)
47
48 #include <sys/sysctl.h>
49
50 int mib[4];
51
52 mib[0] = CTL_KERN;
53 mib[1] = KERN_PROC;
54 mib[2] = KERN_PROC_PATHNAME;
55 mib[3] = -1;
56
57 size_t size = exec_path_sz;
58
59 sysctl (mib, 4, exec_path, &size, NULL, 0);
60
61 const size_t len = strlen (exec_path);
62
63 #else
64 #error Your Operating System is not supported or detected
65 #endif
66
67 exec_path[len] = 0;
68
69 return 0;
70 }
71
get_install_dir(char * install_dir,const char * exec_path)72 static void get_install_dir (char *install_dir, const char *exec_path)
73 {
74 strncpy (install_dir, exec_path, HCBUFSIZ_TINY - 1);
75
76 char *last_slash = NULL;
77
78 if ((last_slash = strrchr (install_dir, '/')) != NULL)
79 {
80 *last_slash = 0;
81 }
82 else if ((last_slash = strrchr (install_dir, '\\')) != NULL)
83 {
84 *last_slash = 0;
85 }
86 else
87 {
88 install_dir[0] = '.';
89 install_dir[1] = 0;
90 }
91 }
92
93 #if defined (_POSIX)
get_profile_dir(char * profile_dir,const char * home_dir)94 static void get_profile_dir (char *profile_dir, const char *home_dir)
95 {
96 snprintf (profile_dir, HCBUFSIZ_TINY, "%s/%s", home_dir, DOT_HASHCAT);
97
98 if (hc_path_is_directory (profile_dir)) return;
99
100 char *xdg_data_home = getenv ("XDG_DATA_HOME");
101
102 if (xdg_data_home)
103 {
104 snprintf (profile_dir, HCBUFSIZ_TINY, "%s/hashcat", xdg_data_home);
105 }
106 else
107 {
108 snprintf (profile_dir, HCBUFSIZ_TINY, "%s/.local/share/hashcat", home_dir);
109 }
110 }
111
get_cache_dir(char * cache_dir,const char * home_dir)112 static void get_cache_dir (char *cache_dir, const char *home_dir)
113 {
114 snprintf (cache_dir, HCBUFSIZ_TINY, "%s/%s", home_dir, DOT_HASHCAT);
115
116 if (hc_path_is_directory (cache_dir)) return;
117
118 char *xdg_cache_home = getenv ("XDG_CACHE_HOME");
119
120 if (xdg_cache_home)
121 {
122 snprintf (cache_dir, HCBUFSIZ_TINY, "%s/hashcat", xdg_cache_home);
123 }
124 else
125 {
126 snprintf (cache_dir, HCBUFSIZ_TINY, "%s/.cache/hashcat", home_dir);
127 }
128 }
129
get_session_dir(char * session_dir,const char * profile_dir)130 static void get_session_dir (char *session_dir, const char *profile_dir)
131 {
132 snprintf (session_dir, HCBUFSIZ_TINY, "%s/%s", profile_dir, SESSIONS_FOLDER);
133 }
134 #endif
135
count_dictionaries(char ** dictionary_files)136 int count_dictionaries (char **dictionary_files)
137 {
138 if (dictionary_files == NULL) return 0;
139
140 int cnt = 0;
141
142 for (int d = 0; dictionary_files[d] != NULL; d++)
143 {
144 cnt++;
145 }
146
147 return (cnt);
148 }
149
first_file_in_directory(const char * path)150 char *first_file_in_directory (const char *path)
151 {
152 DIR *d;
153
154 if ((d = opendir (path)) != NULL)
155 {
156 char *first_file = NULL;
157
158 #if 0
159
160 struct dirent e;
161
162 for (;;)
163 {
164 memset (&e, 0, sizeof (e));
165
166 struct dirent *de = NULL;
167
168 if (readdir_r (d, &e, &de) != 0) break;
169
170 if (de == NULL) break;
171
172 #else
173
174 struct dirent *de;
175
176 while ((de = readdir (d)) != NULL)
177 {
178
179 #endif
180
181 if (de->d_name[0] == '.') continue;
182
183 first_file = strdup (de->d_name);
184
185 break;
186 }
187
188 closedir (d);
189
190 return first_file;
191 }
192
193 return NULL;
194 }
195
196 char **scan_directory (const char *path)
197 {
198 char *tmp_path = hcstrdup (path);
199
200 size_t tmp_path_len = strlen (tmp_path);
201
202 while (tmp_path[tmp_path_len - 1] == '/' || tmp_path[tmp_path_len - 1] == '\\')
203 {
204 tmp_path[tmp_path_len - 1] = 0;
205
206 tmp_path_len = strlen (tmp_path);
207 }
208
209 char **files = NULL;
210
211 size_t num_files = 0;
212
213 DIR *d = NULL;
214
215 if ((d = opendir (tmp_path)) != NULL)
216 {
217 #if 0
218
219 struct dirent e;
220
221 for (;;)
222 {
223 memset (&e, 0, sizeof (e));
224
225 struct dirent *de = NULL;
226
227 if (readdir_r (d, &e, &de) != 0) break;
228
229 if (de == NULL) break;
230
231 #else
232
233 struct dirent *de;
234
235 while ((de = readdir (d)) != NULL)
236 {
237
238 #endif
239
240 if (de->d_name[0] == '.') continue;
241
242 char *path_file;
243
244 hc_asprintf (&path_file, "%s/%s", tmp_path, de->d_name);
245
246 DIR *d_test;
247
248 if ((d_test = opendir (path_file)) != NULL)
249 {
250 closedir (d_test);
251
252 hcfree (path_file);
253 }
254 else
255 {
256 files = (char **) hcrealloc (files, (num_files + 1) * sizeof (char *), sizeof (char *));
257
258 files[num_files] = path_file;
259
260 num_files++;
261 }
262 }
263
264 closedir (d);
265 }
266 else if (errno == ENOTDIR)
267 {
268 files = (char **) hcrealloc (files, (num_files + 1) * sizeof (char *), sizeof (char *));
269
270 files[num_files] = hcstrdup (path);
271
272 num_files++;
273 }
274
275 files = (char **) hcrealloc (files, (num_files + 1) * sizeof (char *), sizeof (char *));
276
277 files[num_files] = NULL;
278
279 hcfree (tmp_path);
280
281 return (files);
282 }
283
284 int folder_config_init (hashcat_ctx_t *hashcat_ctx, MAYBE_UNUSED const char *install_folder, MAYBE_UNUSED const char *shared_folder)
285 {
286 folder_config_t *folder_config = hashcat_ctx->folder_config;
287
288 /**
289 * There's some buggy OpenCL runtime that do not support -I.
290 * A workaround is to chdir() to the OpenCL folder,
291 * then compile the kernels,
292 * then chdir() back to where we came from so we need to save it first
293 * - temporary disabled due to https://github.com/hashcat/hashcat/issues/2379
294 */
295
296 char *cwd = (char *) hcmalloc (HCBUFSIZ_TINY);
297
298 if (getcwd (cwd, HCBUFSIZ_TINY - 1) == NULL)
299 {
300 event_log_error (hashcat_ctx, "getcwd(): %s", strerror (errno));
301
302 hcfree (cwd);
303
304 return -1;
305 }
306
307 /**
308 * folders, as discussed on https://github.com/hashcat/hashcat/issues/20
309 */
310
311 const size_t exec_path_sz = 1024;
312
313 char *exec_path = (char *) hcmalloc (exec_path_sz);
314
315 const int rc = get_exec_path (exec_path, exec_path_sz);
316
317 if (rc == -1)
318 {
319 event_log_error (hashcat_ctx, "get_exec_path() failed.");
320
321 hcfree (cwd);
322
323 hcfree (exec_path);
324
325 return -1;
326 }
327
328 #if defined (_POSIX)
329
330 static const char SLASH[] = "/";
331
332 if (install_folder == NULL) install_folder = SLASH; // makes library use easier
333
334 char *resolved_install_folder = realpath (install_folder, NULL);
335 char *resolved_exec_path = realpath (exec_path, NULL);
336
337 if (resolved_install_folder == NULL) resolved_install_folder = hcstrdup (SLASH);
338
339 /*
340 This causes invalid error out if install_folder (/usr/local/bin) does not exist
341 if (resolved_install_folder == NULL)
342 {
343 event_log_error (hashcat_ctx, "%s: %s", resolved_install_folder, strerror (errno));
344
345 hcfree (cwd);
346
347 hcfree (exec_path);
348
349 hcfree (resolved_install_folder);
350
351 return -1;
352 }
353 */
354
355 if (resolved_exec_path == NULL)
356 {
357 event_log_error (hashcat_ctx, "%s: %s", exec_path, strerror (errno));
358
359 hcfree (cwd);
360
361 hcfree (exec_path);
362
363 hcfree (resolved_install_folder);
364
365 return -1;
366 }
367
368 char *install_dir = (char *) hcmalloc (HCBUFSIZ_TINY);
369
370 get_install_dir (install_dir, resolved_exec_path);
371
372 char *profile_dir = NULL;
373 char *cache_dir = NULL;
374 char *session_dir = NULL;
375 char *shared_dir = NULL;
376
377 if (strcmp (install_dir, resolved_install_folder) == 0)
378 {
379 struct passwd pw;
380 struct passwd *pwp;
381
382 char buf[HCBUFSIZ_TINY];
383
384 getpwuid_r (getuid (), &pw, buf, HCBUFSIZ_TINY, &pwp);
385
386 const char *home_dir = pwp->pw_dir;
387
388 profile_dir = (char *) hcmalloc (HCBUFSIZ_TINY);
389 cache_dir = (char *) hcmalloc (HCBUFSIZ_TINY);
390 session_dir = (char *) hcmalloc (HCBUFSIZ_TINY);
391
392 get_profile_dir (profile_dir, home_dir);
393 get_cache_dir (cache_dir, home_dir);
394 get_session_dir (session_dir, profile_dir);
395
396 shared_dir = hcstrdup (shared_folder);
397
398 hc_mkdir_rec (profile_dir, 0700);
399 hc_mkdir_rec (cache_dir, 0700);
400 hc_mkdir (session_dir, 0700);
401 }
402 else
403 {
404 profile_dir = install_dir;
405 cache_dir = install_dir;
406 session_dir = install_dir;
407 shared_dir = install_dir;
408 }
409
410 hcfree (resolved_install_folder);
411 hcfree (resolved_exec_path);
412
413 #else
414
415 char *install_dir = hcmalloc (HCBUFSIZ_TINY);
416
417 get_install_dir (install_dir, exec_path);
418
419 char *profile_dir = install_dir;
420 char *cache_dir = install_dir;
421 char *session_dir = install_dir;
422 char *shared_dir = install_dir;
423
424 #endif
425
426 hcfree (exec_path);
427
428 /**
429 * There are a lot of problems related to bad support of -I parameters when building the kernel.
430 * Each OpenCL runtime handles it slightly differently.
431 * The most problematic is with new AMD drivers on Windows, which cannot handle quote characters!
432 * The best workaround found so far is to modify the TMP variable (only inside hashcat process) before the runtime is loaded.
433 */
434
435 char *cpath;
436
437 #if defined (_WIN)
438
439 hc_asprintf (&cpath, "%s\\OpenCL\\", shared_dir);
440
441 char *cpath_real;
442
443 hc_asprintf (&cpath_real, "%s\\OpenCL\\", shared_dir);
444
445 #else
446
447 hc_asprintf (&cpath, "%s/OpenCL/", shared_dir);
448
449 char *cpath_real = (char *) hcmalloc (PATH_MAX);
450
451 if (realpath (cpath, cpath_real) == NULL)
452 {
453 event_log_error (hashcat_ctx, "%s: %s", cpath, strerror (errno));
454
455 hcfree (cwd);
456
457 hcfree (shared_dir);
458
459 // Attention: since hcfree () doesn't set the pointer to NULL, we need to do it externally such that
460 // we prevent double-freeing the same memory address (this happens if e.g. profile_dir == session_dir)
461
462 if (profile_dir == shared_dir) profile_dir = NULL;
463 if (cache_dir == shared_dir) cache_dir = NULL;
464 if (session_dir == shared_dir) session_dir = NULL;
465
466 shared_dir = NULL;
467
468
469 hcfree (profile_dir);
470
471 if (session_dir == profile_dir) session_dir = NULL;
472 if (cache_dir == profile_dir) cache_dir = NULL;
473
474 profile_dir = NULL;
475
476
477 hcfree (cache_dir);
478
479 if (session_dir == cache_dir) session_dir = NULL;
480
481 cache_dir = NULL;
482
483 hcfree (session_dir);
484
485 session_dir = NULL;
486
487 hcfree (cpath_real);
488
489 cpath_real = NULL;
490
491 return -1;
492 }
493
494 #endif
495
496 hcfree (cpath);
497
498 //if (getenv ("TMP") == NULL)
499 /* temporary disabled due to https://github.com/hashcat/hashcat/issues/2379
500 if (true)
501 {
502 char *tmp;
503
504 hc_asprintf (&tmp, "TMP=%s", cpath_real);
505
506 putenv (tmp);
507 }
508 */
509
510 // not escaping here, using quotes later
511 // naive_escape (cpath_real, PATH_MAX, ' ', '\\');
512
513 #if defined (_WIN)
514
515 naive_replace (cpath_real, '\\', '/');
516
517 #endif
518
519 /**
520 * kernel cache, we need to make sure folder exist
521 */
522
523 char *kernels_folder;
524
525 hc_asprintf (&kernels_folder, "%s/kernels", cache_dir);
526
527 hc_mkdir (kernels_folder, 0700);
528
529 hcfree (kernels_folder);
530
531 /**
532 * store for later use
533 */
534
535 folder_config->cwd = cwd;
536 folder_config->install_dir = install_dir;
537 folder_config->profile_dir = profile_dir;
538 folder_config->cache_dir = cache_dir;
539 folder_config->session_dir = session_dir;
540 folder_config->shared_dir = shared_dir;
541 folder_config->cpath_real = cpath_real;
542
543 return 0;
544 }
545
546 void folder_config_destroy (hashcat_ctx_t *hashcat_ctx)
547 {
548 folder_config_t *folder_config = hashcat_ctx->folder_config;
549
550 hcfree (folder_config->cpath_real);
551 hcfree (folder_config->cwd);
552 hcfree (folder_config->install_dir);
553
554 memset (folder_config, 0, sizeof (folder_config_t));
555 }
556
557 int hc_mkdir (const char *name, MAYBE_UNUSED const int mode)
558 {
559 #if defined (_WIN)
560 return _mkdir (name);
561 #else
562 return mkdir (name, mode);
563 #endif
564 }
565
566 int hc_mkdir_rec (const char *path, MAYBE_UNUSED const int mode)
567 {
568 char *fullpath = hcstrdup (path);
569
570 char *subpath = dirname (fullpath);
571
572 if (strlen (subpath) > 1)
573 {
574 if (hc_mkdir_rec (subpath, mode) == -1) return -1;
575 }
576
577 if (hc_mkdir (path, mode) == -1)
578 {
579 if (errno != EEXIST) return -1;
580 }
581
582 hcfree (fullpath);
583
584 return 0;
585 }
586