1e21fb479STrond Norbye/*
2e21fb479STrond Norbye *     Copyright 2013 Couchbase, Inc.
3e21fb479STrond Norbye *
4e21fb479STrond Norbye *   Licensed under the Apache License, Version 2.0 (the "License");
5e21fb479STrond Norbye *   you may not use this file except in compliance with the License.
6e21fb479STrond Norbye *   You may obtain a copy of the License at
7e21fb479STrond Norbye *
8e21fb479STrond Norbye *       http://www.apache.org/licenses/LICENSE-2.0
9e21fb479STrond Norbye *
10e21fb479STrond Norbye *   Unless required by applicable law or agreed to in writing, software
11e21fb479STrond Norbye *   distributed under the License is distributed on an "AS IS" BASIS,
12e21fb479STrond Norbye *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e21fb479STrond Norbye *   See the License for the specific language governing permissions and
14e21fb479STrond Norbye *   limitations under the License.
15e21fb479STrond Norbye */
16e21fb479STrond Norbye#include <stdio.h>
17e21fb479STrond Norbye#include <stdlib.h>
18e21fb479STrond Norbye#include <string.h>
19e21fb479STrond Norbye#include <platform/platform.h>
20e21fb479STrond Norbye#include <cbsasl/cbsasl.h>
21e21fb479STrond Norbye#include "cbsasl/cram-md5/hmac.h"
22e21fb479STrond Norbye#include "cbsasl/pwfile.h"
23e21fb479STrond Norbye#include "cbsasl/util.h"
24e21fb479STrond Norbye
25e21fb479STrond Norbyeconst char *cbpwfile = "sasl_server_test.pw";
26e21fb479STrond Norbye
27e21fb479STrond Norbyestatic void create_pw_file()
28e21fb479STrond Norbye{
29e21fb479STrond Norbye    FILE *fp = fopen(cbpwfile, "w");
30e21fb479STrond Norbye    cb_assert(fp != NULL);
31e21fb479STrond Norbye
32e21fb479STrond Norbye    fprintf(fp, "mikewied mikepw \ncseo cpw \njlim jpw \nnopass\n");
33e21fb479STrond Norbye    cb_assert(fclose(fp) == 0);
34e21fb479STrond Norbye
35e21fb479STrond Norbye    putenv("ISASL_PWFILE=sasl_server_test.pw");
36e21fb479STrond Norbye}
37e21fb479STrond Norbye
38e21fb479STrond Norbyestatic void remove_pw_file()
39e21fb479STrond Norbye{
40e21fb479STrond Norbye    cb_assert(remove(cbpwfile) == 0);
41e21fb479STrond Norbye    free_user_ht();
42e21fb479STrond Norbye}
43e21fb479STrond Norbye
44e21fb479STrond Norbyestatic void construct_cram_md5_credentials(char *buffer,
45e21fb479STrond Norbye                                           unsigned *bufferlen,
46e21fb479STrond Norbye                                           const char *user,
47e21fb479STrond Norbye                                           unsigned userlen,
48e21fb479STrond Norbye                                           const char *pass,
49e21fb479STrond Norbye                                           unsigned passlen,
50e21fb479STrond Norbye                                           const char *challenge,
51e21fb479STrond Norbye                                           unsigned challengelen)
52e21fb479STrond Norbye{
53e21fb479STrond Norbye    unsigned char digest[DIGEST_LENGTH];
54e21fb479STrond Norbye    memcpy(buffer, user, userlen);
55e21fb479STrond Norbye    buffer[userlen + 1] = ' ';
56e21fb479STrond Norbye
57e21fb479STrond Norbye    hmac_md5((unsigned char *)challenge, challengelen, (unsigned char *)pass, passlen, digest);
58e21fb479STrond Norbye
59e21fb479STrond Norbye    cbsasl_hex_encode(buffer + userlen + 1, (char *) digest, DIGEST_LENGTH);
60e21fb479STrond Norbye    *bufferlen = 1 + (DIGEST_LENGTH * 2) + userlen;
61e21fb479STrond Norbye}
62e21fb479STrond Norbye
63e21fb479STrond Norbyestatic void test_list_mechs()
64e21fb479STrond Norbye{
65e21fb479STrond Norbye    const char *mechs = NULL;
66e21fb479STrond Norbye    unsigned len = 0;
67e21fb479STrond Norbye    cbsasl_error_t err = cbsasl_list_mechs(&mechs, &len);
68e21fb479STrond Norbye    cb_assert(err == SASL_OK);
69e21fb479STrond Norbye    cb_assert(strncmp(mechs, "CRAM-MD5 PLAIN", len) == 0);
70e21fb479STrond Norbye    cb_assert(strncmp(mechs, "CRDM-MD5 PLAIN", len) != 0);
71e21fb479STrond Norbye}
72e21fb479STrond Norbye
73e21fb479STrond Norbyestatic void test_plain_auth()
74e21fb479STrond Norbye{
75e21fb479STrond Norbye    cbsasl_conn_t *conn = NULL;
76e21fb479STrond Norbye    const char *output = NULL;
77e21fb479STrond Norbye    unsigned outputlen = 0;
78e21fb479STrond Norbye    cbsasl_error_t err;
79e21fb479STrond Norbye
80e21fb479STrond Norbye    err = cbsasl_server_init();
81e21fb479STrond Norbye    cb_assert(err == SASL_OK);
82e21fb479STrond Norbye
83e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "bad_mech", NULL, 0, NULL, NULL);
84e21fb479STrond Norbye    cb_assert(err == SASL_BADPARAM);
85e21fb479STrond Norbye    free((void *)output);
86e21fb479STrond Norbye
87e21fb479STrond Norbye    /* Normal behavior */
88e21fb479STrond Norbye    output = NULL;
89e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "PLAIN", NULL, 0, NULL, NULL);
90e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
91e21fb479STrond Norbye
92e21fb479STrond Norbye    err = cbsasl_server_step(conn, "\0mikewied\0mikepw", 16, &output, &outputlen);
93e21fb479STrond Norbye    cb_assert(err == SASL_OK);
94e21fb479STrond Norbye    free((void *)output);
95e21fb479STrond Norbye    cbsasl_server_term();
96e21fb479STrond Norbye
97e21fb479STrond Norbye
98e21fb479STrond Norbye    /* With wrong password */
99e21fb479STrond Norbye    output = NULL;
100e21fb479STrond Norbye    err = cbsasl_server_init();
101e21fb479STrond Norbye    cb_assert(err == SASL_OK);
102e21fb479STrond Norbye
103e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "PLAIN", NULL, 0, NULL, NULL);
104e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
105e21fb479STrond Norbye
106e21fb479STrond Norbye    err = cbsasl_server_step(conn, "\0mikewied\0badpPW", 16, &output, &outputlen);
107261154c0STrond Norbye    cb_assert(err == SASL_PWERR);
108e21fb479STrond Norbye    free((void *)output);
109e21fb479STrond Norbye
110e21fb479STrond Norbye    cbsasl_dispose(&conn);
111e21fb479STrond Norbye    cb_assert(conn == NULL);
112e21fb479STrond Norbye
113e21fb479STrond Norbye    cbsasl_server_term();
114e21fb479STrond Norbye
115e21fb479STrond Norbye    /* with no password */
116e21fb479STrond Norbye    output = NULL;
117e21fb479STrond Norbye    err = cbsasl_server_init();
118e21fb479STrond Norbye    cb_assert(err == SASL_OK);
119e21fb479STrond Norbye
120e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "PLAIN", NULL, 0, NULL, NULL);
121e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
122e21fb479STrond Norbye
123e21fb479STrond Norbye    err = cbsasl_server_step(conn, "\0nopass\0", 8, &output, &outputlen);
124e21fb479STrond Norbye    cb_assert(err == SASL_OK);
125e21fb479STrond Norbye    free((void *)output);
126e21fb479STrond Norbye
127e21fb479STrond Norbye    cbsasl_server_term();
128e21fb479STrond Norbye
129e21fb479STrond Norbye    /* with authzid */
130e21fb479STrond Norbye    output = NULL;
131e21fb479STrond Norbye    err = cbsasl_server_init();
132e21fb479STrond Norbye    cb_assert(err == SASL_OK);
133e21fb479STrond Norbye
134e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "PLAIN", NULL, 0, NULL, NULL);
135e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
136e21fb479STrond Norbye
137e21fb479STrond Norbye    err = cbsasl_server_step(conn, "funzid\0mikewied\0mikepw", 22, &output, &outputlen);
138e21fb479STrond Norbye    cb_assert(err == SASL_OK);
139e21fb479STrond Norbye    free((void *)output);
140e21fb479STrond Norbye
141e21fb479STrond Norbye    cbsasl_server_term();
142e21fb479STrond Norbye
143e21fb479STrond Norbye    /* with no pw or username ending null */
144e21fb479STrond Norbye    output = NULL;
145e21fb479STrond Norbye    err = cbsasl_server_init();
146e21fb479STrond Norbye    cb_assert(err == SASL_OK);
147e21fb479STrond Norbye
148e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "PLAIN", NULL, 0, NULL, NULL);
149e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
150e21fb479STrond Norbye
151e21fb479STrond Norbye    err = cbsasl_server_step(conn, "funzid\0mikewied", 15, &output, &outputlen);
152e21fb479STrond Norbye    cb_assert(err != SASL_OK);
153e21fb479STrond Norbye    free((void *)output);
154e21fb479STrond Norbye    cbsasl_server_term();
155e21fb479STrond Norbye
156e21fb479STrond Norbye    /* with no nulls at all */
157e21fb479STrond Norbye    output = NULL;
158e21fb479STrond Norbye    err = cbsasl_server_init();
159e21fb479STrond Norbye    cb_assert(err == SASL_OK);
160e21fb479STrond Norbye
161e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "PLAIN", NULL, 0, NULL, NULL);
162e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
163e21fb479STrond Norbye
164e21fb479STrond Norbye    err = cbsasl_server_step(conn, "funzidmikewied", 14, &output, &outputlen);
165e21fb479STrond Norbye    cb_assert(err != SASL_OK);
166e21fb479STrond Norbye    free((void *)output);
167e21fb479STrond Norbye    cbsasl_server_term();
168e21fb479STrond Norbye
169e21fb479STrond Norbye    cbsasl_dispose(&conn);
170e21fb479STrond Norbye    cb_assert(conn == NULL);
171e21fb479STrond Norbye}
172e21fb479STrond Norbye
173e21fb479STrond Norbyestatic void test_cram_md5_auth()
174e21fb479STrond Norbye{
175e21fb479STrond Norbye    const char *user = "mikewied";
176e21fb479STrond Norbye    const char *pass = "mikepw";
177e21fb479STrond Norbye    cbsasl_conn_t *conn = NULL;
178e21fb479STrond Norbye    char creds[128];
179e21fb479STrond Norbye    unsigned credslen = 0;
180e21fb479STrond Norbye    const char *output = NULL;
181e21fb479STrond Norbye    unsigned outputlen = 0;
182e21fb479STrond Norbye
183e21fb479STrond Norbye    cbsasl_error_t err = cbsasl_server_init();
184e21fb479STrond Norbye    cb_assert(err == SASL_OK);
185e21fb479STrond Norbye
186e21fb479STrond Norbye    err = cbsasl_server_start(&conn, "CRAM-MD5", NULL, 0, NULL, NULL);
187e21fb479STrond Norbye    cb_assert(err == SASL_CONTINUE);
188e21fb479STrond Norbye
189e21fb479STrond Norbye    construct_cram_md5_credentials(creds, &credslen, user, strlen(user), pass,
190e21fb479STrond Norbye                                   strlen(pass), conn->c.server.sasl_data,
191e21fb479STrond Norbye                                   conn->c.server.sasl_data_len);
192e21fb479STrond Norbye
193e21fb479STrond Norbye    err = cbsasl_server_step(conn, creds, credslen, &output, &outputlen);
194e21fb479STrond Norbye    cb_assert(err == SASL_OK);
195e21fb479STrond Norbye    if (output != NULL) {
196e21fb479STrond Norbye        free((char *)output);
197e21fb479STrond Norbye    }
198e21fb479STrond Norbye
199e21fb479STrond Norbye    cbsasl_dispose(&conn);
200e21fb479STrond Norbye    cbsasl_server_term();
201e21fb479STrond Norbye    cb_assert(conn == NULL);
202e21fb479STrond Norbye}
203e21fb479STrond Norbye
204e21fb479STrond Norbyeint main()
205e21fb479STrond Norbye{
206e21fb479STrond Norbye    create_pw_file();
207e21fb479STrond Norbye
208e21fb479STrond Norbye    test_list_mechs();
209e21fb479STrond Norbye    test_plain_auth();
210e21fb479STrond Norbye    test_cram_md5_auth();
211e21fb479STrond Norbye
212e21fb479STrond Norbye    remove_pw_file();
213e21fb479STrond Norbye    return 0;
214e21fb479STrond Norbye}