summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/mkhtemp.c
blob: 3e148a4a2fa61780ec6673e9c2292fad5a06b985 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* SPDX-License-Identifier: MIT
 * Copyright (c) 2026 Leah Rowe <leah@libreboot.org>
 *
 * WORK IN PROGRESS (proof of concept), or, v0.0000001
 *
 * Mkhtemp - Hardened mktemp. Create files and directories
 * randomly as determined by user's TMPDIR, or fallback. It
 * attemps to provide mitigation against several TOCTOU-based
 * attacks e.g. directory rename / symlink attacks, and it
 * generally provides much higher strictness than previous
 * implementations such as mktemp, mkstemp or even mkdtemp.
 *
 * Many programs rely on mktemp, and they use TMPDIR in a way
 * that is quite insecure. Mkhtemp intends to change that,
 * quite dramatically, with: userspace sandbox (and use OS
 * level options e.g. OBSD pledge where available), constant
 * identity/ownership checks on files, MUCH stricter ownership
 * restrictions (e.g. enforce sticky bit policy on world-
 * writeable tmpdirs), preventing operation on other people's
 * files (only your own files) - even root is restricted,
 * depending on how the code is compiled. Please read the code.
 *
 * This is the utility version, which makes use of the also-
 * included library. No docs yet - source code are the docs,
 * and the (ever evolving, and hardening) specification.
 *
 * This was written from scratch, for use in nvmutil, and
 * it is designed to be portable (BSD, Linux). Patches
 * very much welcome.
 *
 * WARNING: This is MUCH stricter than every other mktemp
 *          implementation, even more so than mkdtemp or
 *          the OpenBSD version of mkstemp. It *will* break,
 *	    or more specifically, reveal the flaws in, almost
 *	    every major critical infrastructure, because most
 *	    people already use mktemp extremely insecurely.
 *
 * This tool is written by me, for me, and also Libreboot, but
 * it will be summitted for review to various Linux distros
 * and BSD projects once it has reached maturity.
 */

#if defined(__linux__) && !defined(_GNU_SOURCE)
/* for openat2 on linux */
#define _GNU_SOURCE 1
#endif

#ifdef __OpenBSD__
#include <sys/param.h> /* pledge(2) */
#endif

#include <sys/types.h>
#include <sys/stat.h>

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "include/common.h"

int
main(int argc, char *argv[])
{
	char *s = NULL;
	int fd = -1;
	char c;
	int type = MKHTEMP_FILE;
	size_t len;

#if defined (PATH_LEN) && \
    (PATH_LEN) >= 256
	size_t maxlen = PATH_LEN;
#else
	size_t maxlen = 4096;
#endif

/* https://man.openbsd.org/pledge.2 */
#if defined(__OpenBSD__) && defined(OpenBSD)
#if (OpenBSD) >= 509
	if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
		err_no_cleanup(errno, "pledge, main");
#endif
#endif

	while ((c = 
	    getopt(argc, argv, "d")) != -1) {

		switch(c) {
		case 'd':

			type = MKHTEMP_DIR;
			break;
		default:

			err_no_cleanup(EINVAL,
			    "usage: mkhtemp [-d]\n");
		}
	}

	if (new_tmp_common(&fd, &s, type) < 0)
		err_no_cleanup(errno, "%s", s);

#if defined(__OpenBSD__) && defined(OpenBSD)
#if (OpenBSD) >= 509
	if (pledge("stdio", NULL) == -1)
		err_no_cleanup(errno, "pledge, exit");
#endif
#endif

	if (s == NULL)
		err_no_cleanup(EFAULT, "bad string initialisation");

	if (*s == '\0')
		err_no_cleanup(EFAULT, "empty string initialisation");

	if (slen(s, maxlen, &len) < 0)
		err_no_cleanup(EFAULT, "unterminated string initialisation");

	printf("%s\n", s);

	return EXIT_SUCCESS;
}/* 


  ( >:3 )    
   /| |\
    / \





                                                                             */