1 /*
2  * This file is part of John the Ripper password cracker,
3  * Copyright (c) 1996-99,2003,2004,2010,2013 by Solar Designer
4  *
5  * ...with changes in the jumbo patch, by JimF and magnum.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted.
9  *
10  * There's ABSOLUTELY NO WARRANTY, express or implied.
11  */
12 
13 #ifndef _XOPEN_SOURCE
14 #define _XOPEN_SOURCE /* for fileno(3) and fsync(2) */
15 #endif
16 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE /* for strcasestr */
18 #endif
19 
20 #define NEED_OS_FLOCK
21 #include "os.h"
22 
23 #include <stdio.h>
24 #if (!AC_BUILT || HAVE_UNISTD_H) && !_MSC_VER
25 #include <unistd.h>
26 #endif
27 #if !AC_BUILT || HAVE_SYS_FILE_H
28 #include <sys/file.h>
29 #endif
30 #if _MSC_VER
31 #include <io.h>
32 #pragma warning ( disable : 4996 )
33 #define S_IRUSR _S_IREAD
34 #define S_IWUSR _S_IWRITE
35 #endif
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #if (!AC_BUILT || HAVE_FCNTL_H)
39 #include <fcntl.h>
40 #endif
41 #include <errno.h>
42 #include <time.h>
43 #include <stdarg.h>
44 #include <string.h>
45 #include <signal.h>
46 
47 #include "arch.h"
48 #include "misc.h"
49 #include "params.h"
50 #include "path.h"
51 #include "memory.h"
52 #include "status.h"
53 #include "options.h"
54 #include "config.h"
55 #include "recovery.h"
56 #include "unicode.h"
57 #include "dynamic.h"
58 #include "john_mpi.h"
59 #include "cracker.h"
60 #include "signals.h"
61 
62 static int cfg_beep;
63 static int cfg_log_passwords;
64 static int cfg_showcand;
65 static const char *LogDateFormat;
66 static const char *LogDateStderrFormat;
67 static int LogDateFormatUTC=0;
68 static char *log_perms;
69 static char *pot_perms;
70 
71 #ifdef _MSC_VER
72 // I am not sure if there would be other systems which do know know about mode_t
73 typedef unsigned mode_t;
74 #endif
75 
76 // windows does not have these unix specific constants.
77 #ifndef S_ISUID
78 #define S_ISUID 0004000
79 #endif
80 #ifndef S_IXUSR
81 #define S_IXUSR 0000100
82 #endif
83 #ifndef S_IXGRP
84 #define S_IXGRP 0000010
85 #endif
86 #ifndef S_IXOTH
87 #define S_IXOTH 0000001
88 #endif
89 
90 static mode_t perms_t;
91 
92 /*
93  * Note: the file buffer is allocated as (size + LINE_BUFFER_SIZE) bytes
94  * and (ptr - buffer) may actually exceed size by up to LINE_BUFFER_SIZE.
95  * As long as log_file_write() is called after every write to the buffer,
96  * there's always room for at least LINE_BUFFER_SIZE bytes to be added.
97  */
98 struct log_file {
99 	char *name;
100 	char *buffer, *ptr;
101 	int size;
102 	int fd;
103 };
104 
105 #ifdef _MSC_VER
106 // In release mode, the log() function gets in the way of our log struct object
107 #define log local_log_struct
108 #endif
109 
110 static struct log_file log = {NULL, NULL, NULL, 0, -1};
111 static struct log_file pot = {NULL, NULL, NULL, 0, -1};
112 
113 static char *admin_start, *admin_end, *admin_string, *terminal_reset;
114 static int in_logger, show_admins;
115 
log_file_init(struct log_file * f,char * name,char * perms,int size)116 static void log_file_init(struct log_file *f, char *name, char *perms, int size)
117 {
118 	perms_t = strtoul(perms, NULL, 8);
119 
120 	if ((perms_t & (S_IXUSR | S_IXGRP | S_IXOTH | S_ISUID)) ||
121 	    ((perms_t & (S_IRUSR | S_IWUSR)) != (S_IRUSR | S_IWUSR))) {
122 		fprintf(stderr, "%sFilePerms %s invalid\n",
123 		        (f == &log) ? "Log" : "Pot", perms);
124 		error();
125 	}
126 
127 	if (f == &log && (options.flags & FLG_NOLOG)) return;
128 	f->name = name;
129 
130 	if (chmod(path_expand(name), perms_t) && (errno != ENOENT)) {
131 		if (errno == EPERM && cfg_get_bool(SECTION_OPTIONS, NULL,
132 		                                   "IgnoreChmodErrors", 0))
133 			fprintf(stdout, "Note: chmod of %s to %s failed\n",
134 			        path_expand(name), perms);
135 		else
136 			pexit("chmod: %s", path_expand(name));
137 	}
138 
139 #ifndef _MSC_VER
140     umask(000);
141 #endif
142 
143 	if ((f->fd = open(path_expand(name),
144 	    O_WRONLY | O_CREAT | O_APPEND, perms_t)) < 0)
145 		pexit("open: %s", path_expand(name));
146 
147 #ifndef _MSC_VER
148     umask(077);
149 #endif
150 
151 	/*
152 	 * plain will now always be < LINE_BUFFER_SIZE. We add some extra bytes
153 	 * so that there is ALWAYS enough buffer to write our line, and we no
154 	 * longer have to check length before a write (.pot or .log file).
155 	 * The "64" comes from core.
156 	 */
157 	f->ptr = f->buffer =
158 		mem_alloc(size + LINE_BUFFER_SIZE + PLAINTEXT_BUFFER_SIZE + 64);
159 	f->size = size;
160 }
161 
log_file_flush(struct log_file * f)162 static void log_file_flush(struct log_file *f)
163 {
164 	int count;
165 	long int pos_b4 = 0;
166 #if FCNTL_LOCKS
167 	struct flock lock;
168 #endif
169 
170 	if (f->fd < 0) return;
171 
172 	count = f->ptr - f->buffer;
173 	if (count <= 0) return;
174 
175 #if OS_FLOCK || FCNTL_LOCKS
176 #ifdef LOCK_DEBUG
177 	fprintf(stderr, "%s(%u): Locking %s...\n",
178 	        __FUNCTION__, options.node_min, f->name);
179 #endif
180 #if FCNTL_LOCKS
181 	memset(&lock, 0, sizeof(lock));
182 	lock.l_type = F_WRLCK;
183 	while (fcntl(f->fd, F_SETLKW, &lock)) {
184 		if (errno != EINTR)
185 			pexit("fcntl(F_WRLCK)");
186 	}
187 #else
188 	while (flock(f->fd, LOCK_EX)) {
189 		if (errno != EINTR)
190 			pexit("flock(LOCK_EX)");
191 	}
192 #endif
193 #ifdef LOCK_DEBUG
194 	fprintf(stderr, "%s(%u): Locked %s exclusively\n",
195 	        __FUNCTION__, options.node_min, f->name);
196 #endif
197 #endif
198 
199 	if (f == &pot) {
200 		pos_b4 = (long int)lseek(f->fd, 0, SEEK_END);
201 #if defined(LOCK_DEBUG)
202 		fprintf(stderr,
203 		        "%s(%u): writing %d at %ld, ending at %ld to file %s\n",
204 		        __FUNCTION__, options.node_min, count, pos_b4,
205 		        pos_b4+count, f->name);
206 #endif
207 	}
208 
209 	if (write_loop(f->fd, f->buffer, count) < 0) pexit("write");
210 	f->ptr = f->buffer;
211 
212 	if (f == &pot && pos_b4 == crk_pot_pos)
213 		crk_pot_pos += count;
214 
215 #if OS_FLOCK || FCNTL_LOCKS
216 #ifdef LOCK_DEBUG
217 	fprintf(stderr, "%s(%u): Unlocking %s\n",
218 	        __FUNCTION__, options.node_min, f->name);
219 #endif
220 #if FCNTL_LOCKS
221 	lock.l_type = F_UNLCK;
222 	fcntl(f->fd, F_SETLK, &lock);
223 #else
224 	if (flock(f->fd, LOCK_UN))
225 		pexit("flock(LOCK_UN)");
226 #endif
227 #endif
228 
229 #ifdef SIGUSR2
230 	/* We don't really send a sync trigger "at crack" but
231 	   after it's actually written to the pot file. That is, now. */
232 	if (f == &pot && !event_abort && options.reload_at_crack) {
233 #ifdef HAVE_MPI
234 		if (mpi_p > 1) {
235 			int i;
236 
237 			for (i = 0; i < mpi_p; i++) {
238 				if (i == mpi_id)
239 					continue;
240 				if (mpi_req[i] == NULL)
241 					mpi_req[i] = mem_alloc_tiny(
242 						sizeof(MPI_Request),
243 						MEM_ALIGN_WORD);
244 				else
245 					if (*mpi_req[i] != MPI_REQUEST_NULL)
246 						continue;
247 				MPI_Isend("r", 1, MPI_CHAR, i, JOHN_MPI_RELOAD,
248 				          MPI_COMM_WORLD, mpi_req[i]);
249 			}
250 		} else
251 #endif
252 		if (options.fork)
253 			raise(SIGUSR2);
254 	}
255 #endif
256 }
257 
log_file_write(struct log_file * f)258 static int log_file_write(struct log_file *f)
259 {
260 	if (f->fd < 0) return 0;
261 	if (f->ptr - f->buffer > f->size) {
262 		log_file_flush(f);
263 		return 1;
264 	}
265 
266 	return 0;
267 }
268 
log_file_fsync(struct log_file * f)269 static void log_file_fsync(struct log_file *f)
270 {
271 	if (f->fd < 0) return;
272 
273 	log_file_flush(f);
274 #if !HAVE_WINDOWS_H
275 	if (fsync(f->fd)) pexit("fsync");
276 #endif
277 }
278 
log_file_done(struct log_file * f,int do_sync)279 static void log_file_done(struct log_file *f, int do_sync)
280 {
281 	if (f->fd < 0) return;
282 
283 	if (do_sync)
284 		log_file_fsync(f);
285 	else
286 		log_file_flush(f);
287 	if (close(f->fd)) pexit("close");
288 	f->fd = -1;
289 
290 	MEM_FREE(f->buffer);
291 }
292 
log_time(void)293 static int log_time(void)
294 {
295 	int count1, count2;
296 	unsigned int Time;
297 
298 	count1 = 0;
299 
300 	Time = pot.fd >= 0 ? status_get_time() : status_restored_time;
301 
302 	if (LogDateFormat && *LogDateFormat) {
303 		struct tm *t_m;
304 		char Buf[128];
305 		time_t t;
306 
307 		t = time(0);
308 		if (LogDateFormatUTC)
309 			t_m = gmtime(&t);
310 		else
311 			t_m = localtime(&t);
312 		strftime(Buf, sizeof(Buf), LogDateFormat, t_m);
313 		count2 = (int)sprintf(log.ptr + count1, "%s ", Buf);
314 		if (count2 < 0)
315 			return count2;
316 		count1 += count2;
317 	}
318 
319 #ifndef HAVE_MPI
320 	if (options.fork) {
321 #else
322 	if (options.fork || mpi_p > 1) {
323 #endif
324 		count2 = (int)sprintf(log.ptr + count1,
325 		                      "%u ", options.node_min);
326 		if (count2 < 0)
327 			return count2;
328 		count1 += count2;
329 	}
330 
331 	count2 = (int)sprintf(log.ptr + count1, "%u:%02u:%02u:%02u ",
332 	    Time / 86400, Time % 86400 / 3600,
333 	    Time % 3600 / 60, Time % 60);
334 	if (count2 < 0)
335 		return count2;
336 
337 	return count1 + count2;
338 }
339 
340 /*
341  * Change of "^" in passed string to ANSI Escape.
342  * If input is a NULL pointer or feature is disabled, return a null string.
343  */
344 static char *parse_esc(const char *string)
345 {
346 	char *out = str_alloc_copy(string);
347 	char *s = out;
348 
349 	if (!show_admins || !s)
350 		return "";
351 
352 	while (*s) {
353 		if (*s == '^')
354 			*s = 0x1b;
355 		s++;
356 	}
357 
358 	return out;
359 }
360 
361 void log_init(char *log_name, char *pot_name, char *session)
362 {
363 	in_logger = 1;
364 
365 	show_admins = cfg_get_bool(SECTION_OPTIONS, NULL, "MarkAdminCracks", 0);
366 
367 	if (isatty(fileno(stdout))) {
368 		admin_start = parse_esc(cfg_get_param(SECTION_OPTIONS, NULL,
369 		                                      "MarkAdminStart"));
370 		admin_end = parse_esc(cfg_get_param(SECTION_OPTIONS, NULL,
371 		                                    "MarkAdminEnd"));
372 		terminal_reset = parse_esc(cfg_get_param(SECTION_OPTIONS, NULL,
373 		                                         "TerminalReset"));
374 	} else
375 		admin_start = admin_end = terminal_reset = "";
376 
377 	admin_string = parse_esc(cfg_get_param(SECTION_OPTIONS, NULL,
378 	                                       "MarkAdminString"));
379 
380 	if (log_name && log.fd < 0) {
381 		if (session)
382 			log_name = path_session(session, LOG_SUFFIX);
383 		if (!rec_restored && !(options.flags & FLG_NOLOG)) {
384 			const char *protect;
385 			if (!(protect = cfg_get_param(SECTION_OPTIONS, NULL,
386 			                              "LogFileProtect")))
387 				protect = "Disabled";
388 			if (((!strcasecmp(protect, "Named")) &&
389 			     strcmp(log_name, LOG_NAME)) ||
390 			    (!strcasecmp(protect, "Always"))) {
391 				struct stat st;
392 				if (!stat(path_expand(log_name), &st)) {
393 					fprintf(stderr,
394 					        "ERROR: LogFileProtect enabled in john.conf, and %s exists\n",
395 					        path_expand(log_name));
396 					error();
397 				}
398 			}
399 		}
400 		if (!(log_perms = (char*)cfg_get_param(SECTION_OPTIONS, NULL,
401 						"LogFilePermissions")))
402 			log_perms = "0600";
403 
404 		log_file_init(&log, log_name, log_perms , LOG_BUFFER_SIZE);
405 	}
406 
407 	if (pot_name && pot.fd < 0) {
408                 if (!(pot_perms = (char*)cfg_get_param(SECTION_OPTIONS, NULL,
409 						"PotFilePermissions")))
410 			pot_perms = "0600";
411 
412 		log_file_init(&pot, pot_name, pot_perms, POT_BUFFER_SIZE);
413 
414 		cfg_beep = cfg_get_bool(SECTION_OPTIONS, NULL, "Beep", 0);
415 	}
416 
417 	cfg_log_passwords = cfg_get_bool(SECTION_OPTIONS, NULL,
418 	                                 "LogCrackedPasswords", 0);
419 	cfg_showcand = cfg_get_bool(SECTION_OPTIONS, NULL,
420 	                            "StatusShowCandidates", 0);
421 	LogDateFormat = cfg_get_param(SECTION_OPTIONS, NULL,
422 			            "LogDateFormat");
423 	LogDateFormatUTC = cfg_get_bool(SECTION_OPTIONS, NULL,
424 	                            "LogDateFormatUTC", 0);
425 	LogDateStderrFormat = cfg_get_param(SECTION_OPTIONS, NULL,
426 			            "LogDateStderrFormat");
427 	in_logger = 0;
428 }
429 
430 static char *components(char *string, int len)
431 {
432 	static char out[16];
433 	unsigned char *p = (unsigned char*)string;
434 	unsigned char c;
435 	int l, u, d, s, h;
436 
437 	l = u = d = s = h = 0;
438 
439 	while ((c = *p++)) {
440 		if (c >= 'a' && c <= 'z')
441 			l = 1;
442 		else if (c >= 'A' && c <= 'Z')
443 			u = 1;
444 		else if (c >= '0' && c <= '9')
445 			d = 1;
446 		else if (c < 128)
447 			s = 1;
448 		else
449 			h = 1;
450 	}
451 
452 	sprintf(out, "L%d-%s%s%s%s%s", len, l ? "?l" : "", d ? "?d" : "",
453 	        u ? "?u" : "", s ? "?s" : "", h ? "?h" : "");
454 
455 	return out;
456 }
457 
458 /* Quick'n'dirty guess of whether user is an administrator or not */
459 static int is_admin(char *login, char *uid)
460 {
461 	if (login) {
462 		char *s;
463 
464 		if (strcasestr(login, "admin") || strcasestr(login, "root") ||
465 		    strcasestr(login, "super") || strcasestr(login, "sysadm") ||
466 		    !strcasecmp(login, "toor") || !strcasecmp(login, "sa"))
467 			return 1;
468 
469 		/* Avoid false positives for this short substring */
470 		if ((s = strcasestr(login, "adm"))) {
471 			char c;
472 
473 			if (s > login) {
474 				c = s[-1];
475 
476 				if (c < 'A' || c > 'z' ||
477 				    (c > 'Z' && c < 'a'))
478 					return 1;
479 			}
480 
481 			c = s[3];
482 			if (c < 'A' || c > 'z' || (c > 'Z' && c < 'a'))
483 				return 1;
484 		}
485 	}
486 
487 	if (!uid)
488 		return 0;
489 
490 	if (!strcmp(uid, "0"))
491 		return 1;
492 
493 	if (!options.format || !strncasecmp(options.format, "nt", 2) ||
494 	    !strncasecmp(options.format, "lm", 2))
495 		if (!strcmp(uid, "500"))
496 			return 1;
497 
498 	return 0;
499 }
500 
501 #define ADM_START admin ? admin_start : ""
502 #define ADM_END   admin ? admin_end : ""
503 
504 void log_guess(char *login, char *uid, char *ciphertext, char *rep_plain,
505                char *store_plain, char field_sep, int index)
506 {
507 	int count1, count2;
508 	int len;
509 	char *secret = "";
510 	char uid_sep[2] = { 0 };
511 	char *uid_out = "";
512 	int admin = is_admin(login, uid);
513 
514 /* This is because printf("%-16s") does not line up multibyte UTF-8.
515    We need to count characters, not octets. */
516 	if (options.target_enc == UTF_8 || options.report_utf8)
517 		len = strlen8((UTF8*)rep_plain);
518 	else
519 		len = strlen(rep_plain);
520 
521 	if (options.show_uid_in_cracks && uid && *uid) {
522 		uid_sep[0] = field_sep;
523 		uid_out = uid;
524 	}
525 
526 	if (options.verbosity > 1) {
527 		if (options.secure) {
528 			secret = components(rep_plain, len);
529 			printf("%-16s (%s%s%s%s%s)\n", secret,
530 			       ADM_START, login, uid_sep, uid_out, ADM_END);
531 		} else {
532 			char spacer[] = "                ";
533 
534 			spacer[len > 16 ? 0 : 16 - len] = 0;
535 
536 			printf("%s%s (%s%s%s%s%s%s)\n",
537 			       rep_plain, spacer,
538 			       ADM_START, login, uid_sep, uid_out, ADM_END,
539 			       terminal_reset);
540 
541 			if (options.fork)
542 				fflush(stdout);
543 		}
544 	}
545 
546 	in_logger = 1;
547 
548 	if (pot.fd >= 0 && ciphertext ) {
549 #ifndef DYNAMIC_DISABLED
550 		if (!strncmp(ciphertext, "$dynamic_", 9))
551 			ciphertext = dynamic_FIX_SALT_TO_HEX(ciphertext);
552 #endif
553 		if (options.secure) {
554 			secret = components(store_plain, len);
555 			count1 = (int)sprintf(pot.ptr,
556 				                "%s%c%s\n",
557 				                ciphertext,
558 				                field_sep,
559 				                secret);
560 		} else
561 			count1 = (int)sprintf(pot.ptr,
562 				                "%s%c%s\n", ciphertext,
563 				                field_sep, store_plain);
564 		if (count1 > 0) pot.ptr += count1;
565 	}
566 
567 	if (log.fd >= 0) {
568 		count1 = log_time();
569 		if (count1 > 0) {
570 			log.ptr += count1;
571 			count2 = (int)sprintf(log.ptr, "+ Cracked %s%s%s",
572 			                      login, uid_sep, uid_out);
573 
574 			if (options.secure) {
575 				secret = components(rep_plain, len);
576 				count2 += (int)sprintf(log.ptr + count2,
577 				                       ": %s", secret);
578 			} else
579 			if (cfg_log_passwords)
580 				count2 += (int)sprintf(log.ptr + count2,
581 				                       ": %s", rep_plain);
582 			if (admin && *admin_string)
583 				count2 += (int)sprintf(log.ptr + count2,
584 				                       " %s", admin_string);
585 			if (cfg_showcand)
586 				count2 += (int)sprintf(log.ptr + count2,
587 				                       " as candidate #%"PRIu64,
588 				                       status.cands +
589 				                       index + 1);
590 			count2 += (int)sprintf(log.ptr + count2, "\n");
591 
592 			if (count2 > 0)
593 				log.ptr += count2;
594 			else
595 				log.ptr -= count1;
596 		}
597 	}
598 
599 /* Try to keep the two files in sync */
600 	if (log_file_write(&pot))
601 		log_file_flush(&log);
602 	else
603 	if (log_file_write(&log))
604 		log_file_flush(&pot);
605 
606 	in_logger = 0;
607 
608 	if (cfg_beep)
609 		write_loop(fileno(stderr), "\007", 1);
610 }
611 
612 void log_event(const char *format, ...)
613 {
614 	va_list args;
615 	int count1, count2;
616 
617 	if (options.flags & FLG_LOG_STDERR) {
618 		unsigned int Time;
619 
620 		if (LogDateStderrFormat && *LogDateStderrFormat) {
621 			struct tm *t_m;
622 			char Buf[128];
623 			time_t t;
624 
625 			t = time(0);
626 			if (LogDateFormatUTC)
627 				t_m = gmtime(&t);
628 			else
629 				t_m = localtime(&t);
630 			strftime(Buf, sizeof(Buf), LogDateStderrFormat, t_m);
631 			fprintf(stderr, "%s ", Buf);
632 		}
633 
634 #ifndef HAVE_MPI
635 		if (options.fork)
636 #else
637 		if (options.fork || mpi_p > 1)
638 #endif
639 			fprintf(stderr, "%u ", options.node_min);
640 
641 		Time = pot.fd >= 0 ? status_get_time() : status_restored_time;
642 
643 		fprintf(stderr, "%u:%02u:%02u:%02u ",
644 		        Time / 86400, Time % 86400 / 3600,
645 		        Time % 3600 / 60, Time % 60);
646 
647 		va_start(args, format);
648 		vfprintf(stderr, format, args);
649 		va_end(args);
650 		fprintf(stderr, "\n");
651 		if (options.flags & FLG_NOLOG)
652 			return;
653 	}
654 
655 	if (log.fd < 0) return;
656 
657 /*
658  * Handle possible recursion:
659  * log_*() -> ... -> pexit() -> ... -> log_event()
660  */
661 	if (in_logger) return;
662 	in_logger = 1;
663 
664 	count1 = log_time();
665 	if (count1 > 0 &&
666 	    count1 + strlen(format) < LINE_BUFFER_SIZE - 500 - 1) {
667 		log.ptr += count1;
668 
669 		va_start(args, format);
670 		count2 = (int)vsprintf(log.ptr, format, args);
671 		va_end(args);
672 
673 		if (count2 > 0) {
674 			log.ptr += count2;
675 			*log.ptr++ = '\n';
676 		} else
677 			log.ptr -= count1;
678 
679 		if (log_file_write(&log))
680 			log_file_flush(&pot);
681 	}
682 
683 	in_logger = 0;
684 }
685 
686 void log_discard(void)
687 {
688 	if ((options.flags & FLG_NOLOG)) return;
689 	log.ptr = log.buffer;
690 }
691 
692 void log_flush(void)
693 {
694 	in_logger = 1;
695 
696 	if (options.fork)
697 		log_file_flush(&log);
698 	else
699 		log_file_fsync(&log);
700 	log_file_fsync(&pot);
701 
702 	in_logger = 0;
703 }
704 
705 void log_done(void)
706 {
707 /*
708  * Handle possible recursion:
709  * log_*() -> ... -> pexit() -> ... -> log_done()
710  */
711 	if (in_logger) return;
712 	in_logger = 1;
713 
714 	log_file_done(&log, !options.fork);
715 	log_file_done(&pot, 1);
716 
717 	in_logger = 0;
718 }
719