/src/dovecot/src/lib-sasl/dsasl-client-mech-ntlm-dummy.c
Line | Count | Source |
1 | | /* Copyright (c) 2023 Dovecot authors, see the included COPYING file */ |
2 | | |
3 | | #include "lib.h" |
4 | | #include "dsasl-client-private.h" |
5 | | #include "dsasl-client-mech-ntlm-dummy.h" |
6 | | |
7 | | /* Dummy NTLM mechanism |
8 | | |
9 | | This has nothing to do with actual NTLM; it just serves as a means to test |
10 | | the winbind server mechanisms. |
11 | | */ |
12 | | |
13 | | enum ntlm_state { |
14 | | STATE_INIT = 0, |
15 | | STATE_RESPONSE |
16 | | }; |
17 | | |
18 | | struct ntlm_dsasl_client { |
19 | | struct dsasl_client client; |
20 | | enum ntlm_state state; |
21 | | }; |
22 | | |
23 | | void dasl_client_mech_ntlm_init_dummy(void); |
24 | | |
25 | | static enum dsasl_client_result |
26 | | mech_ntlm_input(struct dsasl_client *_client, |
27 | | const unsigned char *input, size_t input_len, |
28 | | const char **error_r) |
29 | 0 | { |
30 | 0 | static const char *challenge = "Challenge"; |
31 | 0 | struct ntlm_dsasl_client *client = |
32 | 0 | container_of(_client, struct ntlm_dsasl_client, client); |
33 | 0 | size_t chal_size; |
34 | |
|
35 | 0 | if (client->state == STATE_RESPONSE) { |
36 | 0 | *error_r = "Server didn't finish authentication"; |
37 | 0 | return DSASL_CLIENT_RESULT_ERR_PROTOCOL; |
38 | 0 | } |
39 | 0 | chal_size = strlen(challenge); |
40 | 0 | if (input_len != chal_size || |
41 | 0 | memcmp(input, challenge, chal_size) != 0) { |
42 | 0 | *error_r = "Invalid challenge"; |
43 | 0 | return DSASL_CLIENT_RESULT_ERR_PROTOCOL; |
44 | 0 | } |
45 | 0 | client->state++; |
46 | 0 | return DSASL_CLIENT_RESULT_OK; |
47 | 0 | } |
48 | | |
49 | | static enum dsasl_client_result |
50 | | mech_ntlm_output(struct dsasl_client *_client, |
51 | | const unsigned char **output_r, size_t *output_len_r, |
52 | | const char **error_r) |
53 | 0 | { |
54 | 0 | struct ntlm_dsasl_client *client = |
55 | 0 | container_of(_client, struct ntlm_dsasl_client, client); |
56 | |
|
57 | 0 | if (_client->set.authid == NULL) { |
58 | 0 | *error_r = "authid not set"; |
59 | 0 | return DSASL_CLIENT_RESULT_ERR_INTERNAL; |
60 | 0 | } |
61 | 0 | if (_client->password == NULL) { |
62 | 0 | *error_r = "password not set"; |
63 | 0 | return DSASL_CLIENT_RESULT_ERR_INTERNAL; |
64 | 0 | } |
65 | | |
66 | 0 | const char *response; |
67 | |
|
68 | 0 | switch (client->state) { |
69 | 0 | case STATE_INIT: |
70 | 0 | *output_r = uchar_empty_ptr; |
71 | 0 | *output_len_r = 0; |
72 | 0 | return DSASL_CLIENT_RESULT_OK; |
73 | 0 | case STATE_RESPONSE: |
74 | 0 | response = t_strconcat("Response: ", _client->set.authid, NULL); |
75 | 0 | *output_r = (const unsigned char *)response; |
76 | 0 | *output_len_r = strlen(response); |
77 | 0 | return DSASL_CLIENT_RESULT_OK; |
78 | 0 | } |
79 | 0 | i_unreached(); |
80 | 0 | } |
81 | | |
82 | | const struct dsasl_client_mech dsasl_client_mech_ntlm = { |
83 | | .name = SASL_MECH_NAME_NTLM, |
84 | | .struct_size = sizeof(struct ntlm_dsasl_client), |
85 | | |
86 | | .input = mech_ntlm_input, |
87 | | .output = mech_ntlm_output |
88 | | }; |
89 | | |
90 | | void dsasl_client_mech_ntlm_init_dummy(void) |
91 | 0 | { |
92 | 0 | dsasl_client_mech_register(&dsasl_client_mech_ntlm); |
93 | 0 | } |