Skip to content

Commit 051c3d6

Browse files
committed
Fix various bugs
- Fix bug that caused lock file to persist between edits - Fix bugs in configuration creation and parsing - Fix bugs in command line parsing
1 parent 6e63867 commit 051c3d6

File tree

8 files changed

+65
-55
lines changed

8 files changed

+65
-55
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.1.0
2+
current_version = 0.2.0
33
message = Bump version: {current_version} → {new_version}
44
commit = True
55
tag = False

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ set(CPACK_PACKAGE_NAME "doas")
6363
set(CPACK_PACKAGE_VENDOR "odedlaz")
6464
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Oded Lazar")
6565
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "execute commands as another user")
66-
set(CPACK_PACKAGE_VERSION "0.1.0")
66+
set(CPACK_PACKAGE_VERSION "0.2.0")
6767
set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
6868
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPU_ARCH}")
6969
set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_SOURCE_DIR}/pkg")

README.md

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,53 +17,6 @@ The gist is that `sudo` is hard to configure and does a lot more then the standa
1717
The original utility only targeted *OpenBSD*, and lacked features that I felt were missing from it and `sudo` as well.
1818
Furthermore, all ports I looked at weren't production read & poorly written.
1919

20-
## Changes compared to the original
21-
22-
### Security checks
23-
24-
The original `doas` doesn't check the owners & permissions of the binary and configuration file.
25-
`sudo` checks those, but only warns the user.
26-
27-
This version ensures the binary and configuration file are owned by `root:root`.
28-
It also ensures the binary has [setuid](https://en.wikipedia.org/wiki/Setuid), and that the configuration file has only read permissions.
29-
30-
Furthermore, only full paths of commands are allowed in the configuration file.
31-
The idea is that privileged users (i.e: members of the *wheel* group) need to explicitly set the rule instead of depending on the running user's path.
32-
33-
### Edit mode
34-
35-
```bash
36-
doas -E
37-
```
38-
39-
`doas` allows any privileged user (i.e: members of the *wheel* group) to edit the configuration file safely.
40-
Furthermore, if the configuration file is corrupted, privileged users can still access it and edit it.
41-
42-
The edit option is similar to `visudo`, it creates a copy of the configuration and updates the real configuration only when the copy is valid.
43-
44-
Non-privileged users are not allowed to edit the configuration.
45-
46-
### Verbose mode
47-
48-
```
49-
doas -V
50-
```
51-
52-
`doas` allows to show logging information to privileged users. That information shows which rules are being loaded & how they are processed.
53-
54-
Non-privileged users are not allowed to turn on verbose mode.
55-
56-
### Dump mode
57-
58-
```
59-
doas -D
60-
```
61-
62-
`doas` allows the user to dump the permissions it loaded to screen.
63-
group permissions and command globs are expanded into individual rules as well.
64-
65-
privileged users see the permissions of all users instead of only their own.
66-
6720
## Project Goals
6821

6922
* ***Secure***. User's must not be able to abuse the utility, and it should protect the user from making stupid mistakes.
@@ -110,6 +63,10 @@ $ mkdir -p doas/build && cd doas/build && cmake .. && cd ..
11063

11164
**[!]** If you're familiar with [direnv](https://oded.blog/2016/12/29/direnv/) and use [fish shell](https://fishshell.com/) you'll enjoy a pre-baked environment.
11265

66+
## Project Status
67+
68+
Version `0.2.0` is out and has complete feature parity with the original `doas`.
69+
11370
## Authors
11471

11572
The main author is [Oded Lazar](https://oded.blog/whoami/)
@@ -122,7 +79,52 @@ If you are interested in contributing but not sure where to start, feel free to
12279

12380
Once I feel this method is not effective anymore, I'll probably create a slack channel or IRC channel.
12481

82+
## Changes compared to the original
83+
84+
### Security checks
85+
86+
The original `doas` doesn't check the owners & permissions of the binary and configuration file.
87+
`sudo` checks those, but only warns the user.
88+
89+
This version ensures the binary and configuration file are owned by `root:root`.
90+
It also ensures the binary has [setuid](https://en.wikipedia.org/wiki/Setuid), and that the configuration file has only read permissions.
91+
92+
Furthermore, only full paths of commands are allowed in the configuration file.
93+
The idea is that privileged users (i.e: members of the *wheel* group) need to explicitly set the rule instead of depending on the running user's path.
94+
95+
### Edit mode
96+
97+
```bash
98+
doas -E
99+
```
100+
101+
`doas` allows any privileged user (i.e: members of the *wheel* group) to edit the configuration file safely.
102+
Furthermore, if the configuration file is corrupted, privileged users can still access it and edit it.
125103

104+
The edit option is similar to `visudo`, it creates a copy of the configuration and updates the real configuration only when the copy is valid.
105+
106+
Non-privileged users are not allowed to edit the configuration.
107+
108+
### Verbose mode
109+
110+
```
111+
doas -V
112+
```
113+
114+
`doas` allows to show logging information to privileged users. That information shows which rules are being loaded & how they are processed.
115+
116+
Non-privileged users are not allowed to turn on verbose mode.
117+
118+
### Dump mode
119+
120+
```
121+
doas -D
122+
```
123+
124+
`doas` allows the user to dump the permissions it loaded to screen.
125+
group permissions and command globs are expanded into individual rules as well.
126+
127+
privileged users see the permissions of all users instead of only their own.
126128
## Examples
127129

128130
Ted Unagst's wrote a great blog post called [doas mastery](https://www.tedunangst.com/flak/post/doas-mastery). Because the project has *complete feature parity* with the OpenBSD version, the mentioned post should be a good starting point.

include/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#pragma once
22

33
namespace doas {
4-
#define VERSION "0.1.0"
4+
#define VERSION "0.2.0"
55
}

man/doas.conf.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ in the **doas.conf** configuration file.
88

99
rules have the following format:
1010

11-
**permit**|**deny** [*options*] *identity* [**as** *target*] [**cmd** *command* [**args** ...]]
11+
**permit**|**deny** [*options*] *identity* [**as** *target*] [**cmd** *command* [**args** ...]]
1212

1313
They consist of the following parts:
1414

src/actions.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ void doas::EditConfiguration(const OptArgs &opts, const Permissions &permissions
8787
if (!utils::AskQuestion(prompt)) {
8888
throw doas::PermissionError("doas.conf is being edited from another session");
8989
}
90+
if (remove(PATH_EDIT_LOCK) != 0) {
91+
throw doas::IOError("%s: %s", PATH_EDIT_LOCK, std::strerror(errno));
92+
}
9093
}
9194

9295
if (!auth::Authenticate(permissions.PamService(), true, true)) {
@@ -99,7 +102,6 @@ void doas::EditConfiguration(const OptArgs &opts, const Permissions &permissions
99102
std::string tmpconf{"/tmp/doas.tmp"};
100103
utils::path::Touch(tmpconf);
101104
Permissions::SecureFile(tmpconf);
102-
utils::path::Copy(PATH_CONFIG, tmpconf);
103105

104106
DEFER({
105107
if (remove(PATH_EDIT_LOCK) != 0) {
@@ -112,6 +114,8 @@ void doas::EditConfiguration(const OptArgs &opts, const Permissions &permissions
112114
}
113115
});
114116

117+
utils::path::Copy(PATH_CONFIG, tmpconf);
118+
115119
std::vector<char *> cmdargv{
116120
strdup(utils::GetEditor().c_str()),
117121
strdup(tmpconf.c_str()),

src/conf.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ const std::vector<std::string> &GetExecutables(const std::string &glob_pattern,
101101

102102
if (retval != 0) {
103103
logger::debug() << "glob(\"" << glob_pattern << "\") returned " << retval << std::endl;
104-
throw doas::IOError("no executables at %s", glob_pattern.c_str());
104+
logger::warning() << "there are no executables at " << glob_pattern << std::endl;
105+
return vec;
105106
}
106107

107108
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
@@ -251,7 +252,10 @@ Permissions::Permissions(const std::string &path, const std::string &auth_servic
251252
: path_{path}, auth_service_{auth_service} {
252253
if (path_ == PATH_CONFIG) {
253254
if (!path::Exists(path_)) {
254-
path::Touch(path_);
255+
std::fstream fs;
256+
fs.open(path_, std::ios::out);
257+
DEFER (fs.close());
258+
fs << "# Welcome to doas!";
255259
Permissions::SecureFile(path_);
256260
}
257261

src/doas.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int Do(Permissions &permissions, const OptArgs &opts) {
103103
// up to here, we don't check if the file is valid
104104
// because the edit config command can edit invalid files
105105
if (!permissions.Size() > 0) {
106-
throw doas::PermissionError("doas.conf is either invalid");
106+
throw doas::PermissionError("doas.conf is either invalid or empty.\n! notice that you're not a member of 'wheel'");
107107
}
108108

109109
if (opts.ShowPermissions()) {

0 commit comments

Comments
 (0)