1 /*
2  *  Copyright (C) 2006  Aaron Stone  <aaron@serendipity.cx>
3  *  Copyright (c) 2005-2012 NFG Net Facilities Group BV support@nfg.nl
4  *
5  *   This program is free software; you can redistribute it and/or
6  *   modify it under the terms of the GNU General Public License
7  *   as published by the Free Software Foundation; either
8  *   version 2 of the License, or (at your option) any later
9  *   version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  *
21  *
22  *
23  *
24  *
25  *
26  *   Basic unit-test framework for dbmail (www.dbmail.org)
27  *
28  *   See http://check.sf.net for details and docs.
29  *
30  *
31  *   Run 'make check' to see some action.
32  *
33  */
34 
35 #include <check.h>
36 #include "check_dbmail.h"
37 #include "dm_cram.h"
38 
39 extern char configFile[PATH_MAX];
40 extern int quiet;
41 extern int reallyquiet;
42 
ci_new(void)43 static ClientBase_T * ci_new(void)
44 {
45 	Mempool_T pool = mempool_open();
46 	ClientBase_T *ci = mempool_pop(pool, sizeof(ClientBase_T));
47 	FILE *fd = fopen("/dev/null","w");
48 	ci->rx = fileno(stdin);
49 	ci->tx = fileno(fd);
50 	ci->pool = pool;
51 	return ci;
52 }
53 
ci_delete(ClientBase_T * ci)54 static void ci_delete(ClientBase_T *ci)
55 {
56 	Mempool_T pool = ci->pool;
57 	mempool_push(pool, ci, sizeof(ClientBase_T));
58 	mempool_close(&pool);
59 }
60 
61 /*
62  *
63  * the test fixtures
64  *
65  */
setup(void)66 void setup(void)
67 {
68 	reallyquiet = 1;
69 	config_get_file();
70 	config_read(configFile);
71 	configure_debug(NULL,511,0);
72 	GetDBParams();
73 	db_connect();
74 	auth_connect();
75 }
76 
teardown(void)77 void teardown(void)
78 {
79 	db_disconnect();
80 	auth_disconnect();
81 }
82 
START_TEST(test_auth_validate)83 START_TEST(test_auth_validate)
84 {
85 	uint64_t user_idnr;
86 	int result;
87 	ClientBase_T *ci = ci_new();
88 
89 	result = auth_validate(ci, "testuser1", "test", &user_idnr);
90 	fail_unless(result==1,"auth_validate failed [%d]", result);
91 	result = auth_validate(ci, "nosuchtestuser", "testnosuchlogin", &user_idnr);
92 	fail_unless(result==0,"auth_validate failed [%d]", result);
93 
94 	ci_delete(ci);
95 }
96 END_TEST
97 
98 #if 0
99 START_TEST(test_auth_change_password)
100 {
101 	uint64_t user_idnr, user_idnr_check;
102 	int result, i;
103 	char *userid = "testchangepass";
104 	char *passwd = "newpassword";
105 	char *password;
106 	char *enctype;
107 	ClientBase_T *ci = ci_new();
108 
109 	if (!auth_user_exists(userid, &user_idnr))
110 		auth_adduser(userid,"initialpassword","", 101, 1002400, &user_idnr);
111 
112 	// Taken from dm_user.c, mkpassword:
113 	/* These are the easy text names. */
114 	const char * const pwtypes[] = {
115 		"plaintext",	"plaintext",	"crypt",	"crypt",
116 		"md5", 		"md5",		"md5sum",	"md5sum",
117 		"md5-hash",	"md5-hash",	"md5-base64",	"md5-digest",
118 		"", 	"", 			NULL
119 	};
120 
121 	for (i = 0; pwtypes[i] != NULL; i++) {
122 		result = mkpassword(userid, passwd, pwtypes[i], "", &password, &enctype);
123 		fail_unless(result==0, "Unable to create password using mkpassword, pwtype [%s].", pwtypes[i]);
124 
125 		result = auth_change_password(user_idnr, password, enctype);
126 		fail_unless(result==0,"auth_change_password failed");
127 
128 		result = auth_validate(ci, userid, passwd, &user_idnr_check);
129 		fail_unless(result==1,"auth_validate failed, pwtype [%s]", pwtypes[i]);
130 		fail_unless(user_idnr_check == user_idnr, "User ID number mismatch from auth_validate.");
131 	}
132 
133 	auth_delete_user(userid);
134 }
135 END_TEST
136 
137 START_TEST(test_auth_change_password_raw)
138 {
139 	uint64_t user_idnr, user_idnr_check;
140 	int result, i;
141 	const char *userid = "testchangepass";
142 	const char *passwd = "yourtest";
143 	char *password;
144 	char *enctype;
145 	ClientBase_T *ci = ci_new();
146 
147 	if (!auth_user_exists(userid, &user_idnr))
148 		auth_adduser(userid,"initialpassword","", 101, 1002400, &user_idnr);
149 
150 	// Taken from dm_user.c, mkpassword:
151 	/* These are the easy text names. */
152 	const char * const pwtypes[] = {
153 		"plaintext-raw",	"crypt-raw",
154 		"md5-raw",		"md5sum-raw",
155 		"md5-hash-raw",		"md5-digest-raw",
156 		"md5-base64-raw",	NULL
157 	};
158 
159 	// Passwords courtest of M.J. O'Brien.
160 	const char * const rawpasswds[] = {
161 		"yourtest",                             "sixG/7CU2FOtg",
162 		"$1$rjN6/GVE$6rPnLX388iJ1Dt7J/LRPf.",   "b22766fada4a17d0f1a67c258a1d93d7",
163 		"$1$rjN6/GVE$6rPnLX388iJ1Dt7J/LRPf.",   "b22766fada4a17d0f1a67c258a1d93d7",
164 		"sidm+tpKF9Dxpnwlih2T1w==",   NULL
165 	};
166 
167 	for (i = 0; pwtypes[i] != NULL; i++) {
168 		result = mkpassword(userid, rawpasswds[i], pwtypes[i], "", &password, &enctype);
169 		fail_unless(result==0, "Unable to create password using mkpassword, pwtype [%s].", pwtypes[i]);
170 
171 		fail_unless(strcmp(password, rawpasswds[i])==0, "Passwords don't match after mkpassword.");
172 
173 		result = auth_change_password(user_idnr, password, enctype);
174 		fail_unless(result==0,"auth_change_password failed");
175 
176 		result = auth_validate(ci, userid, passwd, &user_idnr_check);
177 		fail_unless(result==1,"auth_validate failed, pwtype [%s]", pwtypes[i]);
178 		fail_unless(user_idnr_check == user_idnr, "User ID number mismatch from auth_validate.");
179 	}
180 
181 	auth_delete_user(userid);
182 }
183 END_TEST
184 #endif
185 
START_TEST(test_auth_cram_md5)186 START_TEST(test_auth_cram_md5)
187 {
188 	Cram_T c;
189 	const char *challenge = "<1896.697170952@postoffice.reston.mci.net>";
190 	const char *response = "dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw";
191 	const char *expect = "PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+";
192 	const char *secret = "tanstaaftanstaaf";
193 	const char *ch;
194         char *r;
195 
196 	c = Cram_new();
197 	Cram_setChallenge(c, challenge);
198 
199 	ch = Cram_getChallenge(c);
200 	r = g_base64_encode((guchar *)ch, strlen(ch));
201 	fail_unless(strcmp(r, expect)==0, "%s\n%s\n", r, expect);
202 	g_free(r);
203 
204 	fail_unless(Cram_decode(c, response) == TRUE);
205 	fail_unless(Cram_verify(c, secret) == TRUE);
206 
207 	Cram_free(&c);
208 }
209 END_TEST
210 
211 
dbmail_common_suite(void)212 Suite *dbmail_common_suite(void)
213 {
214 	Suite *s = suite_create("Dbmail Auth");
215 	TCase *tc_auth = tcase_create("Auth");
216 
217 	suite_add_tcase(s, tc_auth);
218 
219 	tcase_add_checked_fixture(tc_auth, setup, teardown);
220 	tcase_add_test(tc_auth, test_auth_validate);
221 	//tcase_add_test(tc_auth, test_auth_change_password);
222 	//tcase_add_test(tc_auth, test_auth_change_password_raw);
223 	tcase_add_test(tc_auth, test_auth_cram_md5);
224 
225 	return s;
226 }
227 
main(void)228 int main(void)
229 {
230 	int nf;
231 	Suite *s = dbmail_common_suite();
232 	SRunner *sr = srunner_create(s);
233 	srunner_run_all(sr, CK_NORMAL);
234 	nf = srunner_ntests_failed(sr);
235 	srunner_free(sr);
236 	return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
237 }
238 
239 
240