Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/lib/iolog/iolog_nextid.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2009-2021 Todd C. Miller <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
21
#include <sys/stat.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#ifdef HAVE_STDBOOL_H
25
# include <stdbool.h>
26
#else
27
# include <compat/stdbool.h>
28
#endif
29
#include <string.h>
30
#include <unistd.h>
31
#include <errno.h>
32
#include <fcntl.h>
33
#include <limits.h>
34
35
#include <sudo_compat.h>
36
#include <sudo_debug.h>
37
#include <sudo_fatal.h>
38
#include <sudo_gettext.h>
39
#include <sudo_iolog.h>
40
#include <sudo_util.h>
41
42
/*
43
* Read the on-disk sequence number, set sessid to the next
44
* number, and update the on-disk copy.
45
* Uses file locking to avoid sequence number collisions.
46
*/
47
bool
48
iolog_nextid(const char *iolog_dir, char sessid[7])
49
{
50
char buf[32], *ep;
51
int i, fd = -1;
52
unsigned long id = 0;
53
size_t len;
54
ssize_t nread;
55
bool ret = false;
56
char pathbuf[PATH_MAX];
57
static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
58
const uid_t iolog_uid = iolog_get_uid();
59
const gid_t iolog_gid = iolog_get_gid();
60
debug_decl(iolog_nextid, SUDO_DEBUG_UTIL);
61
62
/*
63
* Create I/O log directory if it doesn't already exist.
64
*/
65
len = strlcpy(pathbuf, iolog_dir, sizeof(pathbuf));
66
if (len >= sizeof(pathbuf)) {
67
errno = ENAMETOOLONG;
68
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
69
"%s: %s", __func__, iolog_dir);
70
goto done;
71
}
72
if (!iolog_mkdirs(pathbuf))
73
goto done;
74
75
/*
76
* Open sequence file
77
*/
78
len = strlcat(pathbuf, "/seq", sizeof(pathbuf));
79
if (len >= sizeof(pathbuf)) {
80
errno = ENAMETOOLONG;
81
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
82
"%s: %s/seq", __func__, iolog_dir);
83
goto done;
84
}
85
fd = iolog_openat(AT_FDCWD, pathbuf, O_RDWR|O_CREAT);
86
if (fd == -1) {
87
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
88
"%s: unable to open %s", __func__, pathbuf);
89
goto done;
90
}
91
if (!sudo_lock_file(fd, SUDO_LOCK)) {
92
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
93
"unable to lock %s", pathbuf);
94
goto done;
95
}
96
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
97
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
98
"%s: unable to fchown %d:%d %s", __func__,
99
(int)iolog_uid, (int)iolog_gid, pathbuf);
100
}
101
102
/* Read current seq number (base 36). */
103
nread = read(fd, buf, sizeof(buf) - 1);
104
if (nread != 0) {
105
if (nread < 0) {
106
goto done;
107
}
108
if (buf[nread - 1] == '\n')
109
nread--;
110
buf[nread] = '\0';
111
id = strtoul(buf, &ep, 36);
112
if (ep == buf || *ep != '\0' || id >= iolog_get_maxseq()) {
113
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
114
"%s: bad sequence number: %s", pathbuf, buf);
115
id = 0;
116
}
117
}
118
id++;
119
120
/*
121
* Convert id to a string and stash in sessid.
122
* Note that that least significant digits go at the end of the string.
123
*/
124
for (i = 5; i >= 0; i--) {
125
buf[i] = b36char[id % 36];
126
id /= 36;
127
}
128
buf[6] = '\n';
129
130
/* Stash id for logging purposes. */
131
memcpy(sessid, buf, 6);
132
sessid[6] = '\0';
133
134
/* Rewind and overwrite old seq file, including the NUL byte. */
135
if (pwrite(fd, buf, 7, 0) != 7) {
136
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
137
"%s: unable to write %s", __func__, pathbuf);
138
goto done;
139
}
140
ret = true;
141
142
done:
143
if (fd != -1)
144
close(fd);
145
debug_return_bool(ret);
146
}
147
148