git.fiddlerwoaroof.com
Browse code

Merge branch 'jc-token'

Greg Wiley authored on 26/04/2017 18:11:24
Showing 20 changed files
... ...
@@ -2,8 +2,9 @@ CXXFLAGS += -fPIC -fno-stack-protector -std=c++14
2 2
 CFLAGS += -fPIC -fno-stack-protector
3 3
 
4 4
 OBJS = dual_control.o request.o dual_control_integrate.o validator.o conversation.o user.o \
5
-	   sys_unistd.o sys_pwd.o
6
-TESTS = dual_control_test validator_test conversation_test request_test user_test
5
+		sys_unistd.o sys_pwd.o token.o sys_fstream.o sys_syslog.o logger.o
6
+TESTS = dual_control_test validator_test conversation_test request_test user_test token_test \
7
+		logger_test
7 8
 TESTOBJS = $(patsubst %,%.o,$(TESTS))
8 9
 SRCS := $(OBJS:.o=.cc) $(TESTOBJS:.o=.cc)
9 10
 
... ...
@@ -72,68 +72,3 @@ conversation create_conversation (pam &pam)
72 72
     return conversation (std::shared_ptr<conversation_ifc> (new impl (pam)));
73 73
 }
74 74
 
75
-/*
76
-int (*conv)(int num_msg, const struct pam_message **msg,
77
-                struct pam_response **resp, void *appdata_ptr)
78
-   */
79
-
80
-/*
81
-pam_token_conversation::pam_token_conversation (pam_handle_t *pamh,
82
-        const pam_p pam)
83
-{
84
-    pam_conversation_p pam_conversation;
85
-    int get_conversation_result = pam->get_conversation (pamh,
86
-                                  pam_conversation);
87
-
88
-    if (get_conversation_result != 0) {
89
-        return;
90
-    }
91
-
92
-    struct pam_message prompt;
93
-
94
-    std::string message ("Dual control token: ");
95
-
96
-    prompt.msg = const_cast<char *> (message.c_str());
97
-
98
-    prompt.msg_style = PAM_PROMPT_ECHO_OFF;
99
-
100
-    std::vector<const struct pam_message *> prompts (1);
101
-
102
-    prompts[0] = &prompt;
103
-
104
-    std::vector<struct pam_response *> answers (1);
105
-
106
-    int conversation_result = pam_conversation->conv (prompts, answers);
107
-
108
-    if (conversation_result) {
109
-        return;
110
-    }
111
-
112
-    if (answers[0]->resp_retcode) {
113
-        return;
114
-    }
115
-
116
-    std::string answer (answers[0]->resp);
117
-    std::string::iterator delim = std::find (answer.begin(), answer.end(), ':');
118
-
119
-    if (delim == answer.end()) {
120
-        return;
121
-    }
122
-
123
-    std::string user_name (answer.begin(), delim);
124
-    std::string token (delim + 1, answer.end());
125
-    user_ = user_name;
126
-    token_ = token;
127
-}
128
-
129
-std::string pam_token_conversation::token()
130
-{
131
-    return token_;
132
-}
133
-
134
-std::string pam_token_conversation::user_name()
135
-{
136
-    return user_;
137
-}
138
-*/
139
-
... ...
@@ -17,6 +17,7 @@
17 17
 #include "dual_control.h"
18 18
 #include "conversation.h"
19 19
 #include "validator.h"
20
+#include "logger.h"
20 21
 
21 22
 int dual_control_ifc::authenticate (const pam_request &request)
22 23
 {
... ...
@@ -39,7 +39,7 @@ void use_conversation (dual_control_configuration &config,
39 39
 
40 40
 void use_logger (dual_control_configuration &config, logger_ifc *value)
41 41
 {
42
-    config.logger = logger (share (value));
42
+    config.logger = logger (logger::delegate (value));
43 43
 }
44 44
 
45 45
 class mock_logger : public logger_ifc
46 46
new file mode 100755
... ...
@@ -0,0 +1,25 @@
1
+#!/bin/bash
2
+
3
+
4
+for f in "${@}"; do
5
+  astyle -q --options=$(dirname $0)/astylerc $f
6
+  echo "" >> $f
7
+  if ! grep -q 'Copyright.*CJ' $f; then
8
+      cat << EOF > $f.temp_
9
+/* Copyright (C) CJ Affiliate
10
+ *
11
+ * You may use, distribute and modify this code under  the
12
+ * terms of the  GNU General Public License  version 2  or
13
+ * later.
14
+ *
15
+ * You should have received a copy of the license with this
16
+ * file. If not, you will find a copy in the "LICENSE" file
17
+ * at https://github.com/cjdev/dual-control.
18
+ */
19
+
20
+EOF
21
+  fi
22
+  cat -s $f >> $f.temp_
23
+  mv $f.temp_ $f
24
+done
25
+
0 26
new file mode 100644
... ...
@@ -0,0 +1,64 @@
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
+
12
+#include <syslog.h>
13
+#include <security/pam_modules.h>
14
+
15
+#include "sys_syslog.h"
16
+#include "logger.h"
17
+
18
+namespace
19
+{
20
+class impl : public logger_ifc
21
+{
22
+private:
23
+    sys_syslog syslog_;
24
+public:
25
+    impl (const sys_syslog &sys_syslog) : syslog_ (sys_syslog) {}
26
+    void log (int result, const std::string &user_name,
27
+              const std::string &token)
28
+    {
29
+        std::string message;
30
+        int facility;
31
+        int priority;
32
+
33
+        switch (result) {
34
+        case PAM_SUCCESS:
35
+            facility = LOG_AUTHPRIV;
36
+            priority = LOG_NOTICE;
37
+            message = user_name + " " + token + " " + "success";
38
+            break;
39
+
40
+        case PAM_AUTH_ERR:
41
+            facility = LOG_AUTHPRIV;
42
+            priority = LOG_NOTICE;
43
+            message = user_name + " " + token + " " + "fail";
44
+            break;
45
+
46
+        default:
47
+            facility = LOG_AUTH;
48
+            priority = LOG_ERR;
49
+            message = user_name + " pam returned error";
50
+            break;
51
+        }
52
+
53
+        syslog_.openlog ("dual-control", 0, facility);
54
+        syslog_.syslog (priority, message.c_str());
55
+        syslog_.closelog();
56
+    }
57
+};
58
+}
59
+
60
+logger logger::create (const sys_syslog &sys_syslog)
61
+{
62
+    return logger (delegate (new impl (sys_syslog)));
63
+}
64
+
... ...
@@ -15,6 +15,8 @@
15 15
 #include <memory>
16 16
 #include <string>
17 17
 
18
+#include "sys_syslog.h"
19
+
18 20
 class logger_ifc
19 21
 {
20 22
 public:
... ...
@@ -25,17 +27,20 @@ public:
25 27
 
26 28
 class logger : public logger_ifc
27 29
 {
30
+public:
31
+    typedef std::shared_ptr<logger_ifc> delegate;
28 32
 private:
29
-    std::shared_ptr<logger_ifc> delegate_;
33
+    delegate delegate_;
30 34
 public:
31
-    logger (const std::shared_ptr<logger_ifc> &delegate) : delegate_
35
+    logger (const delegate &delegate) : delegate_
32 36
         (delegate) {}
33
-    logger() : logger (std::shared_ptr<logger_ifc> (new logger_ifc)) {}
37
+    logger() : logger (delegate (new logger_ifc)) {}
34 38
     void log (int result, const std::string &user_name,
35 39
               const std::string &token)
36 40
     {
37 41
         delegate_->log (result, user_name, token);
38 42
     }
43
+    static logger create (const sys_syslog &sys_syslog);
39 44
 };
40 45
 
41 46
 #endif
42 47
new file mode 100644
... ...
@@ -0,0 +1,211 @@
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
+
12
+#include <syslog.h>
13
+#include <security/pam_modules.h>
14
+
15
+#include <iostream>
16
+
17
+#include "sys_syslog.h"
18
+#include "logger.h"
19
+#include "test_util.h"
20
+
21
+class mock_syslog : public sys_syslog_ifc
22
+{
23
+public:
24
+    int facility;
25
+    std::string message;
26
+    int priority;
27
+    bool closed;
28
+    std::string ident;
29
+    mock_syslog() : closed (false), facility (-1000), priority (-1000) {}
30
+    void openlog (const char *ident, int logopt, int facility)
31
+    {
32
+        this->facility = facility;
33
+        this->ident = ident;
34
+    }
35
+    void vsyslog (int priority, const char *message, va_list args)
36
+    {
37
+        this->priority = priority;
38
+        this->message = message;
39
+    }
40
+    void closelog()
41
+    {
42
+        this->closed = true;
43
+    }
44
+
45
+};
46
+
47
+int logs_success()
48
+{
49
+    //given
50
+    mock_syslog *capture = new mock_syslog;
51
+    sys_syslog::delegate test_delegate (capture);
52
+    sys_syslog test_syslog (test_delegate);
53
+    logger logger = logger::create (test_syslog);
54
+    std::string user ("user");
55
+    std::string token ("token");
56
+
57
+    //when
58
+    logger.log (PAM_SUCCESS, user, token);
59
+
60
+    //then
61
+    check (capture->facility == LOG_AUTHPRIV, "facility does not match");
62
+    check (capture->message == user + " " + token + " " + "success",
63
+           "message does not match");
64
+    check (capture->priority == LOG_NOTICE, "priority does not match");
65
+    check (capture->closed, "syslog not closed");
66
+    check (capture->ident == "dual-control", "dual-control");
67
+    succeed();
68
+}
69
+
70
+int logs_failure()
71
+{
72
+    //given
73
+    mock_syslog *capture = new mock_syslog;
74
+    sys_syslog::delegate test_delegate (capture);
75
+    sys_syslog test_syslog (test_delegate);
76
+    logger logger = logger::create (test_syslog);
77
+    std::string user ("user");
78
+    std::string token ("token");
79
+
80
+    //when
81
+    logger.log (PAM_AUTH_ERR, user, token);
82
+
83
+    //then
84
+    check (capture->facility == LOG_AUTHPRIV, "facility does not match");
85
+    check (capture->message == user + " " + token + " " + "fail",
86
+           "message does not match");
87
+    check (capture->priority == LOG_NOTICE, "priority does not match");
88
+    check (capture->closed, "syslog not closed");
89
+    check (capture->ident == "dual-control", "dual-control");
90
+    succeed();
91
+}
92
+
93
+int logs_pam_service_error()
94
+{
95
+    //given
96
+    mock_syslog *capture = new mock_syslog;
97
+    sys_syslog::delegate test_delegate (capture);
98
+    sys_syslog test_syslog (test_delegate);
99
+    logger logger = logger::create (test_syslog);
100
+    std::string user ("user");
101
+    std::string token ("token");
102
+
103
+    //when
104
+    logger.log (PAM_SERVICE_ERR, user, token);
105
+
106
+    //then
107
+    check (capture->facility == LOG_AUTH, "facility does not match");
108
+    check (capture->message == user + " pam returned error",
109
+           "message does not match");
110
+    check (capture->priority == LOG_ERR, "priority does not match");
111
+    check (capture->closed, "syslog not closed");
112
+    check (capture->ident == "dual-control", "dual-control");
113
+    succeed();
114
+}
115
+
116
+RESET_VARS_START
117
+RESET_VARS_END
118
+
119
+int run_tests()
120
+{
121
+    test (logs_success);
122
+    test (logs_failure);
123
+    test (logs_pam_service_error);
124
+    succeed();
125
+}
126
+
127
+int main (int numargs, char **args)
128
+{
129
+    return !run_tests();
130
+}
131
+
132
+/*
133
+int logged_priority = -1000;
134
+const char *logged_message = "";
135
+void fake_syslog (int priority, const char *message, ...)
136
+{
137
+    logged_priority = priority;
138
+    logged_message = message;
139
+}
140
+
141
+int close_log_invoked = 0;
142
+void fake_closelog (void)
143
+{
144
+    close_log_invoked = 1;
145
+}
146
+
147
+int opened_facility = -1000;
148
+const char *opened_program_name = "";
149
+int opened_logopt = -1000;
150
+void fake_openlog (const char *ident, int logopt, int facility)
151
+{
152
+    opened_facility = facility;
153
+    opened_program_name = ident;
154
+    opened_logopt = logopt;
155
+}
156
+
157
+RESET_VARS_START
158
+logged_priority = -1000;
159
+close_log_invoked = 0;
160
+opened_facility = -1000;
161
+const char *opened_program_name = "";
162
+int opened_logopt = -1000;
163
+RESET_VARS_END
164
+
165
+int test_log_success()
166
+{
167
+    // given
168
+
169
+    // when
170
+    log_success();
171
+
172
+    // then
173
+    checkint (LOG_AUTHPRIV, opened_facility, "facility");
174
+    checkint (LOG_NOTICE, logged_priority, "priority");
175
+    checkint (0, opened_logopt, "logopt");
176
+    check (close_log_invoked, "log closed");
177
+    checkstr ("pam_dual_control", opened_program_name, "program name");
178
+    checkstr ("dual control succeeded", logged_message, "logged message");
179
+    succeed();
180
+}
181
+
182
+int test_log_failure()
183
+{
184
+    //given
185
+
186
+    //when
187
+    log_failure();
188
+
189
+    //then
190
+    checkint (LOG_AUTHPRIV, opened_facility, "facility");
191
+    checkint (LOG_NOTICE, logged_priority, "priority");
192
+    checkint (0, opened_logopt, "logopt");
193
+    check (close_log_invoked, "log closed");
194
+    checkstr ("pam_dual_control", opened_program_name, "program name");
195
+    checkstr ("dual control failed", logged_message, "logged message");
196
+    succeed();
197
+}
198
+
199
+int test_runner()
200
+{
201
+    test (test_log_success);
202
+    test (test_log_failure);
203
+    succeed();
204
+}
205
+
206
+int main (int numargs, char **args)
207
+{
208
+    return !test_runner();
209
+}
210
+*/
211
+
0 212
deleted file mode 100644
... ...
@@ -1,32 +0,0 @@
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
-
12
-#include <syslog.h>
13
-
14
-#include "logging.h"
15
-#include "test_support.h"
16
-
17
-static const char program_name[] = "pam_dual_control";
18
-
19
-void log_success()
20
-{
21
-    openlog (program_name, 0, LOG_AUTHPRIV);
22
-    syslog (LOG_NOTICE, "dual control succeeded");
23
-    closelog();
24
-}
25
-
26
-void log_failure()
27
-{
28
-    openlog (program_name, 0, LOG_AUTHPRIV);
29
-    syslog (LOG_NOTICE, "dual control failed");
30
-    closelog();
31
-}
32
-
33 0
deleted file mode 100644
... ...
@@ -1,96 +0,0 @@
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
-
12
-#include <cstdio>
13
-#include <cstring>
14
-#include <syslog.h>
15
-
16
-#include "logging.h"
17
-#include "test_util.h"
18
-
19
-int logged_priority = -1000;
20
-const char *logged_message = "";
21
-void fake_syslog (int priority, const char *message, ...)
22
-{
23
-    logged_priority = priority;
24
-    logged_message = message;
25
-}
26
-
27
-int close_log_invoked = 0;
28
-void fake_closelog (void)
29
-{
30
-    close_log_invoked = 1;
31
-}
32
-
33
-int opened_facility = -1000;
34
-const char *opened_program_name = "";
35
-int opened_logopt = -1000;
36
-void fake_openlog (const char *ident, int logopt, int facility)
37
-{
38
-    opened_facility = facility;
39
-    opened_program_name = ident;
40
-    opened_logopt = logopt;
41
-}
42
-
43
-RESET_VARS_START
44
-logged_priority = -1000;
45
-close_log_invoked = 0;
46
-opened_facility = -1000;
47
-const char *opened_program_name = "";
48
-int opened_logopt = -1000;
49
-RESET_VARS_END
50
-
51
-int test_log_success()
52
-{
53
-    // given
54
-
55
-    // when
56
-    log_success();
57
-
58
-    // then
59
-    checkint (LOG_AUTHPRIV, opened_facility, "facility");
60
-    checkint (LOG_NOTICE, logged_priority, "priority");
61
-    checkint (0, opened_logopt, "logopt");
62
-    check (close_log_invoked, "log closed");
63
-    checkstr ("pam_dual_control", opened_program_name, "program name");
64
-    checkstr ("dual control succeeded", logged_message, "logged message");
65
-    succeed();
66
-}
67
-
68
-int test_log_failure()
69
-{
70
-    //given
71
-
72
-    //when
73
-    log_failure();
74
-
75
-    //then
76
-    checkint (LOG_AUTHPRIV, opened_facility, "facility");
77
-    checkint (LOG_NOTICE, logged_priority, "priority");
78
-    checkint (0, opened_logopt, "logopt");
79
-    check (close_log_invoked, "log closed");
80
-    checkstr ("pam_dual_control", opened_program_name, "program name");
81
-    checkstr ("dual control failed", logged_message, "logged message");
82
-    succeed();
83
-}
84
-
85
-int test_runner()
86
-{
87
-    test (test_log_success);
88
-    test (test_log_failure);
89
-    succeed();
90
-}
91
-
92
-int main (int numargs, char **args)
93
-{
94
-    return !test_runner();
95
-}
96
-
97 0
new file mode 100644
... ...
@@ -0,0 +1,35 @@
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
+
12
+#include <memory>
13
+#include <fstream>
14
+
15
+#include "sys_fstream.h"
16
+
17
+namespace
18
+{
19
+class impl : public fstreams_ifc
20
+{
21
+public:
22
+    pstream open_fstream (const std::string &file_path)
23
+    {
24
+        return pstream (new std::ifstream (file_path));
25
+    }
26
+};
27
+
28
+}
29
+
30
+fstreams fstreams::create()
31
+{
32
+    static fstreams singleton (delegate (new impl));
33
+    return singleton;
34
+}
35
+
0 36
new file mode 100644
... ...
@@ -0,0 +1,45 @@
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
+
12
+#ifndef SYS_FSTREAM_H
13
+#define SYS_FSTREAM_H
14
+
15
+#include <memory>
16
+#include <sstream>
17
+
18
+class fstreams_ifc
19
+{
20
+public:
21
+    typedef std::shared_ptr<std::istream> pstream;
22
+    virtual pstream open_fstream (const std::string &file_path)
23
+    {
24
+        return pstream (new std::istringstream (""));
25
+    }
26
+};
27
+
28
+class fstreams : public fstreams_ifc
29
+{
30
+public:
31
+    typedef std::shared_ptr<fstreams_ifc> delegate;
32
+private:
33
+    delegate delegate_;
34
+public:
35
+    fstreams (const delegate &delegate) : delegate_ (delegate) {}
36
+    fstreams() : fstreams (delegate (new fstreams_ifc)) {}
37
+    pstream open_fstream (const std::string &file_path)
38
+    {
39
+        return delegate_->open_fstream (file_path);
40
+    }
41
+    static fstreams create();
42
+};
43
+
44
+#endif
45
+
0 46
new file mode 100644
... ...
@@ -0,0 +1,43 @@
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
+
12
+#include <syslog.h>
13
+
14
+#include "sys_syslog.h"
15
+
16
+namespace
17
+{
18
+class impl : public sys_syslog_ifc
19
+{
20
+public:
21
+    void openlog (const char *ident, int logopt, int facility)
22
+    {
23
+        ::openlog (ident, logopt, facility);
24
+    }
25
+
26
+    void vsyslog (int priority, const char *message, va_list args)
27
+    {
28
+        ::vsyslog (priority, message, args);
29
+    }
30
+
31
+    void closelog()
32
+    {
33
+        ::closelog();
34
+    }
35
+};
36
+}
37
+
38
+sys_syslog sys_syslog::create()
39
+{
40
+    static sys_syslog singleton (sys_syslog::delegate (new impl));
41
+    return singleton;
42
+}
43
+
0 44
new file mode 100644
... ...
@@ -0,0 +1,60 @@
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
+
12
+#ifndef SYS_SYSLOG_H
13
+#define SYS_SYSLOG_H
14
+
15
+#include <memory>
16
+#include <cstdarg>
17
+#include <syslog.h>
18
+
19
+class sys_syslog_ifc
20
+{
21
+public:
22
+    virtual void openlog (const char *ident, int logopt, int facility) {}
23
+    virtual void vsyslog (int priority, const char *message, va_list args) {}
24
+    virtual void closelog() {}
25
+};
26
+
27
+class sys_syslog : public sys_syslog_ifc
28
+{
29
+public:
30
+    typedef std::shared_ptr<sys_syslog_ifc> delegate;
31
+private:
32
+    delegate delegate_;
33
+public:
34
+    sys_syslog (const delegate &delegate) : delegate_ (delegate) {}
35
+    sys_syslog() : sys_syslog (delegate (new sys_syslog_ifc)) {}
36
+    void openlog (const char *ident, int logopt, int facility)
37
+    {
38
+        delegate_->openlog (ident, logopt, facility);
39
+    }
40
+    void syslog (int priority, const char *format, ...)
41
+    {
42
+        va_list vargs;
43
+        va_start (vargs, format);
44
+        vsyslog (priority, format, vargs);
45
+        va_end (vargs);
46
+    }
47
+    void vsyslog (int priority, const char *message, va_list vargs)
48
+    {
49
+        delegate_->vsyslog (priority, message, vargs);
50
+    }
51
+    void closelog()
52
+    {
53
+        delegate_->closelog();
54
+    }
55
+
56
+    static sys_syslog create();
57
+};
58
+
59
+#endif
60
+
... ...
@@ -1,7 +1,7 @@
1 1
 /* Copyright (C) CJ Affiliate
2 2
  *
3 3
  * You may use, distribute and modify this code under  the
4
- * terms of the  GNU General Public License  version 2  or
4
+ * terms of the  GNU General Public License version 2  or
5 5
  * later.
6 6
  *
7 7
  * You should have received a copy of the license with this
... ...
@@ -9,17 +9,43 @@
9 9
  * at https://github.com/cjdev/dual-control.
10 10
  */
11 11
 
12
-#include <cstdlib>
13
-#include <cstring>
14
-#include <security/pam_modules.h>
15
-#include <pwd.h>
16
-#include <unistd.h>
17
-#include <cstdio>
18
-#include <sys/stat.h>
19 12
 #include <string>
20 13
 #include <vector>
21 14
 #include <memory>
22 15
 #include <fstream>
23 16
 
24
-#include "test_support.h"
17
+#include "token.h"
18
+#include "user.h"
19
+#include "sys_fstream.h"
20
+
21
+namespace
22
+{
23
+class user_token_supplier_impl : public user_token_supplier_ifc
24
+{
25
+private:
26
+    fstreams fstreams_;
27
+public:
28
+    user_token_supplier_impl (fstreams &fstreams) :
29
+        fstreams_ (fstreams) {}
30
+    std::string token (user &user)
31
+    {
32
+        const std::string file_path (user.home_directory() + "/.dual_control");
33
+        std::vector<char> line (7);
34
+
35
+        fstreams::pstream stream (fstreams_.open_fstream (file_path));
36
+
37
+        if (!stream->good()) {
38
+            return "";
39
+        }
40
+
41
+        stream->getline (line.data(), line.size());
42
+        return std::string (line.data());
43
+    }
44
+};
45
+}
46
+user_token_supplier user_token_supplier::create (fstreams &fstreams)
47
+{
48
+    return user_token_supplier (user_token_supplier::delegate
49
+                                (new user_token_supplier_impl (fstreams)));
50
+}
25 51
 
... ...
@@ -11,15 +11,18 @@
11 11
 
12 12
 #ifndef _TOKEN_H
13 13
 #define _TOKEN_H
14
+
14 15
 #include <string>
15 16
 #include <memory>
16
-#include <iostream>
17
+
17 18
 #include "user.h"
19
+#include "sys_fstream.h"
18 20
 
19 21
 class user_token_supplier_ifc
20 22
 {
21 23
 public:
22
-    virtual std::string token (const user &user)
24
+    virtual ~user_token_supplier_ifc() {}
25
+    virtual std::string token (user &user)
23 26
     {
24 27
         return "";
25 28
     }
... ...
@@ -27,17 +30,20 @@ public:
27 30
 
28 31
 class user_token_supplier : public user_token_supplier_ifc
29 32
 {
33
+public:
34
+    typedef std::shared_ptr<user_token_supplier_ifc> delegate;
30 35
 private:
31
-    std::shared_ptr<user_token_supplier_ifc> delegate_;
36
+    delegate delegate_;
32 37
 public:
33
-    user_token_supplier (std::shared_ptr<user_token_supplier_ifc> delegate) :
38
+    user_token_supplier (delegate delegate) :
34 39
         delegate_ (delegate) {}
35 40
     user_token_supplier() : user_token_supplier (
36
-            std::shared_ptr<user_token_supplier_ifc> (new user_token_supplier_ifc)) {}
37
-    std::string token (const user &user)
41
+            delegate (new user_token_supplier_ifc)) {}
42
+    std::string token (user &user)
38 43
     {
39 44
         return delegate_->token (user);
40 45
     }
46
+    static user_token_supplier create (fstreams &fstreams);
41 47
 };
42 48
 
43 49
 #endif
... ...
@@ -9,129 +9,111 @@
9 9
  * at https://github.com/cjdev/dual-control.
10 10
  */
11 11
 
12
+#include <memory>
12 13
 #include <cstring>
13 14
 #include <pwd.h>
14 15
 #include <cstdio>
15 16
 #include <sys/stat.h>
17
+#include <fstream>
18
+#include <sstream>
16 19
 
17 20
 #include "token.h"
18 21
 #include "test_util.h"
22
+#include "user.h"
23
+#include "sys_fstream.h"
19 24
 
20
-const char *fake_user = "";
21
-const char *fake_user_token = "";
22
-
23
-// all the fake system calls
24
-const char *fake_home_dir = "";
25
-int fake_getpwnam_r (const char *nam, struct passwd *pwd, char *buffer,
26
-                     size_t bufsize, struct passwd **result)
27
-{
28
-    strcpy (buffer, fake_home_dir);
29
-    pwd->pw_dir = buffer;
30
-    int ok = !strcmp (nam, fake_user);
31
-    *result = ok ? pwd : 0;
32
-    return !ok;
33
-}
34
-
35
-const char *fake_stat_path = "";
36
-int fake_stat (const char *path, struct stat *stat)
37
-{
38
-    return (strcmp (fake_stat_path, path));
39
-}
40
-
41
-const char *fake_fopen_path = "";
42
-const char *fake_fopen_mode = "";
43
-FILE *_fhandle = 0;
44
-FILE *fake_fopen (const char *path, const char *mode)
25
+class fake_user : public user_ifc
45 26
 {
46
-    static FILE handle;
47
-    int path_matches = !strcmp (fake_fopen_path, path);
48
-    int mode_matches = !strcmp (fake_fopen_mode, mode);
49
-
50
-    if (path_matches && mode_matches) {
51
-        _fhandle = &handle;
52
-        return &handle;
53
-    } else {
54
-        _fhandle = 0;
55
-        return 0;
27
+private:
28
+    std::string home_directory_;
29
+public:
30
+    fake_user() {}
31
+    fake_user (const std::string &home_directory) :
32
+        home_directory_ (home_directory)
33
+    {
56 34
     }
57
-}
58
-
59
-char *fake_fgets (char *buf, int n, FILE *fp)
60
-{
61
-    if (_fhandle == fp && fp != 0) {
62
-        strncpy (buf, fake_user_token, n - 1);
63
-        return buf;
64
-    } else {
65
-        return 0;
35
+    std::string home_directory()
36
+    {
37
+        return home_directory_;
66 38
     }
67
-}
68
-
69
-int fake_fclose (FILE *fp)
70
-{
71
-    return 0;
72
-}
39
+};
73 40
 
74
-// STDIO
75
-
76
-RESET_VARS_START
77
-fake_user = "msmith";
78
-fake_user_token = "123456";
79
-fake_home_dir = "/home/msmith";
80
-fake_stat_path = "/home/msmith/.dual_control";
81
-fake_fopen_path = fake_stat_path;
82
-fake_fopen_mode = "r";
83
-RESET_VARS_END
84
-
85
-int validate_compares_to_user_token()
41
+class fake_fstreams : public fstreams_ifc
86 42
 {
43
+private:
44
+    std::string expected_file_path_;
45
+    std::string file_contents_;
46
+public:
47
+    fake_fstreams (const std::string &expected_file_path,
48
+                   const std::string &file_contents)
49
+        : expected_file_path_ (expected_file_path),
50
+          file_contents_ (file_contents) {}
51
+    pstream open_fstream (const std::string &file_path)
52
+    {
53
+        if (file_path == expected_file_path_) {
54
+            return fstreams::pstream (new std::istringstream (file_contents_));
55
+        } else {
56
+            return fstreams_ifc::open_fstream (file_path);
57
+        }
87 58
 
88
-    // given
89
-
90
-    // when
91
-    int valid = validate_token ("msmith", "123456");
92
-
93
-    // then
94
-    check (valid, "expected result to be valid");
95
-
96
-    succeed();
97
-
98
-}
59
+    }
60
+};
99 61
 
100
-int validates_from_the_right_user()
62
+int reads_from_the_right_file ()
101 63
 {
102 64
     //given
65
+    std::string home_directory = "/somedir";
66
+    // hardcoded file name is .dual_control in the user's home directory
67
+    std::string token_file = home_directory + "/.dual_control";
68
+    std::string token ("123456");
69
+    fstreams test_streams (fstreams::delegate (new fake_fstreams (token_file,
70
+                           token)));
71
+
72
+    //file_reader test_file_reader (file_reader::delegate (new fake_file_reader));
73
+    user test_user (user::delegate (new fake_user (home_directory)));
74
+    user_token_supplier supplier (user_token_supplier::create (
75
+                                      test_streams));
103 76
 
104 77
     //when
105
-    int valid = validate_token ("jbalcita", "12346");
78
+    std::string actual = supplier.token (test_user);
106 79
 
107 80
     //then
108
-    check (!valid, "expected result to be invalid");
81
+    check (actual == token, "token does not match");
109 82
     succeed();
110 83
 }
111 84
 
112
-int validates_user_specific_token()
85
+int returns_empty_string_if_file_open_fail()
113 86
 {
114 87
     //given
88
+    std::string home_directory = "/somedir";
89
+    // hardcoded file name is .dual_control in the user's home directory
90
+    std::string token_file = home_directory + "/.not_dual_control";
91
+    fstreams test_streams (fstreams::delegate (new fake_fstreams (token_file,
92
+                           "654321")));
93
+    user test_user (user::delegate (new fake_user (home_directory)));
94
+    user_token_supplier supplier (user_token_supplier::create (
95
+                                      test_streams));
115 96
 
116 97
     //when
117
-    int valid = validate_token ("msmith", "654321");
98
+    std::string actual = supplier.token (test_user);
118 99
 
119 100
     //then
120
-    check (!valid, "expected result to be invalid");
101
+    check (actual == "", "should have returned empty string");
121 102
     succeed();
122 103
 }
123 104
 
124
-int runtests()
105
+RESET_VARS_START
106
+RESET_VARS_END
107
+
108
+int run_tests()
125 109
 {
126
-    test (validate_compares_to_user_token);
127
-    test (validates_from_the_right_user);
128
-    test (validates_user_specific_token);
110
+    test (reads_from_the_right_file);
111
+    test (returns_empty_string_if_file_open_fail);
129 112
     succeed();
130 113
 }
131 114
 
132
-int main (int argc, char **argv)
115
+int main (int argc, char *argv[])
133 116
 {
134
-    int rval = !runtests();
135
-    return rval;
117
+    return !run_tests();
136 118
 }
137 119
 
... ...
@@ -11,6 +11,7 @@
11 11
 
12 12
 #include <memory>
13 13
 #include <vector>
14
+#include <iostream>
14 15
 
15 16
 #include "user.h"
16 17
 #include "sys_unistd.h"
... ...
@@ -18,6 +19,21 @@
18 19
 
19 20
 namespace
20 21
 {
22
+class user_impl : public user_ifc
23
+{
24
+private:
25
+    std::string home_directory_;
26
+    std::string user_name_;
27
+public:
28
+    user_impl (const passwd user_info) :
29
+        home_directory_ (std::string (user_info.pw_dir)),
30
+        user_name_ (std::string (user_info.pw_name)) {}
31
+    std::string home_directory()
32
+    {
33
+        return home_directory_;
34
+    }
35
+};
36
+
21 37
 class directory_impl : public directory_ifc
22 38
 {
23 39
 private:
... ...
@@ -35,7 +51,7 @@ public:
35 51
         std::vector<user> return_value;
36 52
 
37 53
         if (!result && found_passwd) {
38
-            return_value.push_back (user());
54
+            return_value.push_back (user::delegate (new user_impl (sys_passwd)));
39 55
         }
40 56
 
41 57
         return return_value;
... ...
@@ -48,41 +64,3 @@ directory directory::create (unistd &unistd, pwd &pwd)
48 64
     return directory (delegate (new directory_impl (unistd, pwd)));
49 65
 }
50 66
 
51
-/*
52
-class concrete_user : public user
53
-{
54
-private:
55
-    std::vector<char> buffer_;
56
-    std::shared_ptr<struct passwd> store_;
57
-public:
58
-    concrete_user (const std::vector<char> &buffer,
59
-                   const std::shared_ptr<struct passwd> &store);
60
-};
61
-
62
-concrete_user::concrete_user (const std::vector<char> &buffer,
63
-                              const std::shared_ptr<struct passwd> &store) :
64
-    buffer_ (buffer),
65
-    store_ (store),
66
-    user (store.get())
67
-{
68
-}
69
-
70
-const std::shared_ptr<user> create_user (const std::string &user_name)
71
-{
72
-    std::vector<char> buffer (sysconf (_SC_GETPW_R_SIZE_MAX));
73
-    std::shared_ptr<struct passwd> sys_passwd (new struct passwd);
74
-    struct passwd *found_passwd (0);
75
-
76
-    getpwnam_r (user_name.c_str(), sys_passwd.get(), buffer.data(),
77
-                buffer.size(), &found_passwd);
78
-
79
-    std::shared_ptr<user> rval;
80
-
81
-    if (found_passwd) {
82
-        rval.reset (new concrete_user (buffer, sys_passwd));
83
-    }
84
-
85
-    return rval;
86
-}
87
-*/
88
-
... ...
@@ -14,7 +14,7 @@
14 14
 #include <vector>
15 15
 #include <string>
16 16
 #include <memory>
17
-
17
+#include <iostream>
18 18
 #include "sys_unistd.h"
19 19
 #include "sys_pwd.h"
20 20
 
... ...
@@ -22,15 +22,28 @@ class user_ifc
22 22
 {
23 23
 public:
24 24
     virtual ~user_ifc() {}
25
+    virtual std::string home_directory()
26
+    {
27
+        return "virtual";
28
+    }
25 29
 };
26 30
 
27 31
 class user : public user_ifc
28 32
 {
33
+public:
34
+    typedef std::shared_ptr<user_ifc> delegate;
29 35
 private:
30
-    std::shared_ptr<user_ifc> delegate_;
36
+    delegate delegate_;
31 37
 public:
32
-    user (std::shared_ptr<user_ifc> delegate) : delegate_ (delegate) {}
33
-    user() : user (std::shared_ptr<user_ifc> (new user_ifc)) {}
38
+    user (delegate delegate) : delegate_ (delegate)
39
+    {
40
+    }
41
+    user() : user (delegate (new user_ifc)) {}
42
+    std::string home_directory()
43
+    {
44
+        return delegate_-> home_directory();
45
+    }
46
+    static user create (const passwd &passwd);
34 47
 };
35 48
 
36 49
 class directory_ifc
... ...
@@ -46,7 +46,7 @@ private:
46 46
 public:
47 47
     fake_user_token_supplier (const std::string &token) : token_ (token) {}
48 48
     fake_user_token_supplier() : token_ ("_NOT_A_TOKEN") {}
49
-    virtual std::string token (const user &user)
49
+    std::string token (user &user)
50 50
     {
51 51
         return token_;
52 52
     }