git.fiddlerwoaroof.com
Browse code

Update README and reformat

Ed Langley authored on 17/06/2017 00:35:58
Showing 23 changed files
... ...
@@ -1,31 +1,32 @@
1 1
 [![Build Status](https://travis-ci.org/cjdev/dual-control.svg?branch=master)](https://travis-ci.org/cjdev/dual-control)
2 2
 
3 3
 # Dual Control
4
-Dual Control is a PAM module that requires a user to input a generated token
5
-from another user before being granted resource access. The module also requires
6
-that the user input the reason for his or her access request and, via `syslog`,
7
-captures all this information for future reference.
8 4
 
9
-At **CJ Engineering**, we will be implementing Dual Control on our production
10
-boxes to ensure that a single engineer cannot use sudo to gain application-roles
11
-access without meeting the above-stated requirements.
5
+Dual Control is a PAM module that requires a user to input a generated token from another user before being
6
+granted resource access. The module also requires that the user input the reason for his or her access request
7
+and, via `syslog`, captures all this information for future reference.
12 8
 
13
-Dual Control is an open source project licensed under the
14
-[GNU General Public License](https://github.com/cjdev/dual-control/blob/master/LICENSE).
15
-As it stands, Dual Control is written only for machines running Linux. However,
16
-we graciously welcome contributions, particularly those related to portability
17
-to other operating systems.
9
+At **CJ Engineering**, we will be implementing Dual Control on our production boxes to ensure that a single
10
+engineer cannot use sudo to gain application-roles access without meeting the above-stated requirements.
11
+
12
+Dual Control is an open source project licensed under the [GNU General Public
13
+License](https://github.com/cjdev/dual-control/blob/master/LICENSE).  As it stands, Dual Control is written
14
+only for machines running Linux. However, we graciously welcome contributions, particularly those related to
15
+portability to other operating systems.
18 16
 
19 17
 ## Status
20
-This is in active development. The current version uses a permanent token and
21
-so is not meant for production use. The final version will use a time-based OTP.
18
+
19
+This is in active development. The current version uses a permanent token and so is not meant for production
20
+use. The final version will use a time-based OTP.
22 21
 
23 22
 ## Install
23
+
24 24
 - Obtain and install the RPM
25 25
   - build yourself using the code in https://github.com/cjdev/dual-control-rpm, or
26 26
   - get it from a developer
27 27
 - Edit the `/etc/pam.d/sudo`  (this is for CentOS 7, others may be different)
28 28
   - replace the existing auth lines with
29
+
29 30
 ```
30 31
 #%PAM-1.0
31 32
 # auth        include       system-auth
... ...
@@ -41,17 +42,21 @@ session     required      pam_limits.so
41 42
 ```
42 43
 
43 44
 ## Add a dual control token
44
-From the authorizer's account home, run `dual_control`. The resulting token can
45
-be used to authorize another user.
45
+
46
+From the authorizer's account home, run `setup_user_account.sh`. This generates a secret key for TOTP
47
+authentication and, if you have qrencode installed, generates a QR code to scan.  Scan or enter this key in
48
+your authenticator app and then verify that the token in your app matches the one on the screen (answer Y to
49
+the prompt to get a more recent token).
46 50
 
47 51
 ## Use
48
-- log in with a test user that has `sudo` ability (not the vagrant account it is too
49
-powerful)
52
+
53
+- log in with a test user that has `sudo` ability (not the vagrant account it is too powerful)
50 54
 - type `sudo bash`
51 55
 - enter your password
52 56
 - enter dual control token, authorizer's username + ':' + authorizer's token
53 57
 
54 58
 ## Build and test
59
+
55 60
 - ./configure
56 61
 - make
57 62
 - make test
... ...
@@ -190,10 +190,13 @@ private:
190 190
 
191 191
     }
192 192
 
193
-    uint8_t get_next_input(reverse_map &lookup_table, std::string &input, std::string::size_type idx) const {
193
+    uint8_t get_next_input (reverse_map &lookup_table, std::string &input,
194
+                            std::string::size_type idx) const
195
+    {
194 196
         character_type character = input[idx];
195 197
 
196
-        if (character != '=' && lookup_table.find(character) == lookup_table.end()) {
198
+        if (character != '='
199
+            && lookup_table.find (character) == lookup_table.end()) {
197 200
             throw invalid_data_exception ();
198 201
         }
199 202
 
... ...
@@ -215,7 +218,7 @@ public:
215 218
             uint8_t start_bit = bits_written % 8;
216 219
             std::vector<unsigned char>::size_type current_byte = bits_written/8;
217 220
 
218
-            uint8_t val = get_next_input(lookup_table, input, idx);
221
+            uint8_t val = get_next_input (lookup_table, input, idx);
219 222
             set_vector_at_bit (result, val, current_byte, start_bit, 5);
220 223
 
221 224
             bits_written += 5;
... ...
@@ -231,3 +234,4 @@ template class std::vector<unsigned char>;
231 234
 base32::base32 ():
232 235
     delegate_ (std::make_shared<base32_impl> ())
233 236
 {}
237
+
... ...
@@ -65,6 +65,7 @@ int decode_validates_input()
65 65
     base32 codec = base32();
66 66
 
67 67
     int num_exceptions = 0;
68
+
68 69
     try {
69 70
         codec.decode ("A");
70 71
         codec.decode ("AAAAAAAAA");
... ...
@@ -80,7 +81,7 @@ int decode_validates_input()
80 81
         num_exceptions++;
81 82
     }
82 83
 
83
-    check(num_exceptions == 2, "base32.decode should validate input data");
84
+    check (num_exceptions == 2, "base32.decode should validate input data");
84 85
 
85 86
     succeed();
86 87
 }
... ...
@@ -117,3 +118,4 @@ int main (int argc, char *argv[])
117 118
 {
118 119
     return !run_tests();
119 120
 }
121
+
... ...
@@ -1,3 +1,14 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
1 12
 #ifndef _BECOME_H
2 13
 #define _BECOME_H
3 14
 
... ...
@@ -6,20 +17,21 @@
6 17
 
7 18
 class become
8 19
 {
9
- private:
20
+private:
10 21
     unistd unistd_;
11
- public:
12
- become(user user, unistd &unistd) :
13
-    unistd_ (unistd)
22
+public:
23
+    become (user user, unistd &unistd) :
24
+        unistd_ (unistd)
14 25
     {
15 26
         uid_t uid = user.uid();
16
-        unistd_.seteuid(uid);
27
+        unistd_.seteuid (uid);
17 28
     }
18 29
 
19 30
     ~become()
20 31
     {
21
-        unistd_.seteuid(0);
32
+        unistd_.seteuid (0);
22 33
     }
23 34
 };
24 35
 
25 36
 #endif
37
+
... ...
@@ -1,3 +1,14 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
1 12
 #include "become.h"
2 13
 #include "sys_unistd.h"
3 14
 #include "sys_pwd.h"
... ...
@@ -43,9 +54,10 @@ public:
43 54
 int become_calls_seteuid_with_right_arguments ()
44 55
 {
45 56
     uid_t expected_uid = 1000;
46
-    std::shared_ptr<mock_unistd> mock_unistd  = share (new class mock_unistd(expected_uid));
57
+    std::shared_ptr<mock_unistd> mock_unistd  = share (new class mock_unistd (
58
+                expected_uid));
47 59
     unistd fake_unistd (mock_unistd);
48
-    user fake_user (share (new class fake_user(expected_uid)));
60
+    user fake_user (share (new class fake_user (expected_uid)));
49 61
 
50 62
     become become_ (fake_user, fake_unistd);
51 63
 
... ...
@@ -64,3 +76,4 @@ int main (int argc, char *argv[])
64 76
 {
65 77
     return !run_tests();
66 78
 }
79
+
... ...
@@ -76,3 +76,4 @@ dual_control dual_control::create (const dual_control_configuration
76 76
     return dual_control (std::shared_ptr<dual_control_ifc> (new impl (
77 77
                              configuration)));
78 78
 }
79
+
... ...
@@ -72,3 +72,4 @@ PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh, int flags, int argc,
72 72
 {
73 73
     return dc.setcred (pam_request ( pamh, flags, argc, argv));
74 74
 }
75
+
... ...
@@ -95,8 +95,9 @@ private:
95 95
                       size_t data_size, const int digits=6) const
96 96
     {
97 97
         // TODO: see if I can use sha256/etc. with google auth...
98
-        const unsigned char *digest = HMAC (EVP_sha1(), key.data(), key.size(), data,
99
-                                      data_size, NULL, NULL);
98
+        const unsigned char *digest = HMAC (EVP_sha1(), key.data(), key.size(),
99
+                                            data,
100
+                                            data_size, NULL, NULL);
100 101
 
101 102
         if (digest == nullptr) {
102 103
             throw hmac_failed_exception();
... ...
@@ -137,3 +138,4 @@ totp_generator::totp_generator (
137 138
     const int code_digits) :
138 139
     delegate_ (std::make_shared<token_generator_impl> (clock, code_digits))
139 140
 {}
141
+
... ...
@@ -192,3 +192,4 @@ int main (int argc, char *argv[])
192 192
 {
193 193
     return !run_tests();
194 194
 }
195
+
... ...
@@ -62,3 +62,4 @@ installer installer::create (const tokens &tokens, const unistd &unistd,
62 62
     return installer (std::make_shared<impl> (tokens, unistd, directory,
63 63
                       generator));
64 64
 }
65
+
... ...
@@ -211,3 +211,4 @@ int main (int argc, char *argv[])
211 211
 {
212 212
     return !run_tests();
213 213
 }
214
+
... ...
@@ -25,9 +25,9 @@ public:
25 25
     {
26 26
         return ::getlogin();
27 27
     }
28
-    virtual int seteuid(uid_t euid) const override
28
+    virtual int seteuid (uid_t euid) const override
29 29
     {
30
-        return ::seteuid(euid);
30
+        return ::seteuid (euid);
31 31
     };
32 32
 };
33 33
 }
... ...
@@ -37,3 +37,4 @@ unistd unistd::create()
37 37
     static unistd sys_unistd (unistd::delegate (new impl));
38 38
     return sys_unistd;
39 39
 }
40
+
... ...
@@ -28,7 +28,7 @@ public:
28 28
     {
29 29
         return "";
30 30
     }
31
-    virtual int seteuid(uid_t euid) const
31
+    virtual int seteuid (uid_t euid) const
32 32
     {
33 33
         return -1;
34 34
     };
... ...
@@ -54,9 +54,9 @@ public:
54 54
     {
55 55
         return delegate_->getlogin();
56 56
     }
57
-    int seteuid(uid_t euid) const
57
+    int seteuid (uid_t euid) const
58 58
     {
59
-        return delegate_->seteuid(euid);
59
+        return delegate_->seteuid (euid);
60 60
     };
61 61
     static unistd create();
62 62
 };
... ...
@@ -64,3 +64,4 @@ public:
64 64
 template class std::shared_ptr<unistd_ifc>;
65 65
 
66 66
 #endif
67
+
... ...
@@ -118,3 +118,4 @@ tokens tokens::create (const fstreams &fstreams,
118 118
     return tokens (tokens::delegate
119 119
                    (new tokens_impl (fstreams, generator, rand)));
120 120
 }
121
+
... ...
@@ -333,3 +333,4 @@ int main (int argc, char *argv[])
333 333
 {
334 334
     return !run_tests();
335 335
 }
336
+
... ...
@@ -1,8 +1,19 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
1 12
 #ifndef TYPEALIASEES_H_
2 13
 #define TYPEALIASEES_H_
3 14
 #include <vector>
4 15
 
5 16
 using octet_vector = typename std::vector<uint8_t>;
6 17
 
7
-
8 18
 #endif
19
+
... ...
@@ -87,3 +87,4 @@ directory directory::create (unistd &unistd, pwd &pwd)
87 87
 {
88 88
     return directory (delegate (new directory_impl (unistd, pwd)));
89 89
 }
90
+
... ...
@@ -56,7 +56,7 @@ public:
56 56
         }
57 57
 
58 58
         auto user_ = found_user[0];
59
-        become become_(user_, unistd_);
59
+        become become_ (user_, unistd_);
60 60
 
61 61
         std::string user_token = tokens_.token (user_);
62 62
         return user_token == token;
... ...
@@ -68,6 +68,8 @@ validator validator::create (const directory &directory,
68 68
                              const tokens &tokens,
69 69
                              const unistd &unistd)
70 70
 {
71
-    std::shared_ptr<validator_ifc> delegate (new impl (directory, tokens, unistd));
71
+    std::shared_ptr<validator_ifc> delegate (new impl (directory, tokens,
72
+            unistd));
72 73
     return validator (delegate);
73 74
 }
75
+
... ...
@@ -36,7 +36,7 @@ public:
36 36
 
37 37
     int seteuid (uid_t euid) const override
38 38
     {
39
-        actual_uids.push_back(euid);
39
+        actual_uids.push_back (euid);
40 40
         return (euid == expected_euid_ || euid == 0) ? 0 : -1;
41 41
     }
42 42
 };
... ...
@@ -60,7 +60,8 @@ private:
60 60
     std::string user_name_;
61 61
     uid_t uid_;
62 62
 public:
63
-    fake_directory (const std::string &user_name, const uid_t uid = -1) : user_name_ (user_name), uid_ (uid)
63
+    fake_directory (const std::string &user_name,
64
+                    const uid_t uid = -1) : user_name_ (user_name), uid_ (uid)
64 65
     {
65 66
     }
66 67
     fake_directory() : user_name_ ("_NOT_A_USER") {}
... ...
@@ -70,7 +71,7 @@ public:
70 71
         std::vector<user> result;
71 72
 
72 73
         if (user_name == user_name_) {
73
-            result.push_back (user(share (new fake_user (uid_))));
74
+            result.push_back (user (share (new fake_user (uid_))));
74 75
         }
75 76
 
76 77
         return result;
... ...
@@ -101,7 +102,8 @@ bool validator_validates()
101 102
 
102 103
     uid_t expected_uid = 1000;
103 104
     directory directory (share (new fake_directory (user_name, expected_uid)));
104
-    std::shared_ptr<mock_unistd> mock_unistd = share (new class mock_unistd(expected_uid));
105
+    std::shared_ptr<mock_unistd> mock_unistd = share (new class mock_unistd (
106
+                expected_uid));
105 107
     class unistd unistd (mock_unistd);
106 108
     validator validator = validator::create (directory, tokens, unistd);
107 109
     std::vector<uid_t> expected_uids {expected_uid, 0};
... ...
@@ -111,7 +113,8 @@ bool validator_validates()
111 113
 
112 114
     // then
113 115
     check (actual, "should be valid");
114
-    check (mock_unistd->actual_uids == expected_uids, "should drop permissions");
116
+    check (mock_unistd->actual_uids == expected_uids,
117
+           "should drop permissions");
115 118
     succeed();
116 119
 }
117 120
 
... ...
@@ -234,3 +237,4 @@ int main (int argc, char *argv[])
234 237
 {
235 238
     return !run_tests();
236 239
 }
240
+