mech-cram-md5.c revision b44650b0f48a4b5f0dc240ed836833a00b643b9f
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen/* Copyright (C) 2002,2003 Timo Sirainen / Joshua Goodall */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen/* CRAM-MD5 SASL authentication, see RFC-2195
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen Joshua Goodall <joshua@roughtrade.net> */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen /* requested: */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen /* received: */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen unsigned long maxbuf;
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainenstatic const char *get_cram_challenge(void)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return t_strdup_printf("<%s.%s@%s>", (const char *)buf,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool verify_credentials(struct cram_auth_request *request,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen const unsigned char *credentials, size_t size)
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_error(&request->auth_request, "cram-md5",
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen "invalid credentials length");
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen hmac_md5_update(&ctx, request->challenge, strlen(request->challenge));
a7790b4f44c743a821fa065084fd6286767bfa8aTimo Sirainen response_hex = binary_to_hex(digest, sizeof(digest));
a7790b4f44c743a821fa065084fd6286767bfa8aTimo Sirainen if (memcmp(response_hex, request->response, sizeof(digest)*2) != 0) {
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_info(&request->auth_request, "cram-md5",
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "password mismatch");
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool parse_cram_response(struct cram_auth_request *request,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char **error_r)
3a734c9c3efd87864d1ad860826fd4e787457bedTimo Sirainen /* <username> SPACE <response>. Username may contain spaces, so assume
3a734c9c3efd87864d1ad860826fd4e787457bedTimo Sirainen the rightmost space is the response separator. */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request->username = p_strndup(request->pool, data, space);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen p_strndup(request->pool, data + space, size - space);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic void credentials_callback(enum passdb_result result,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen const unsigned char *credentials, size_t size,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen if (verify_credentials(request, credentials, size))
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainenmech_cram_md5_auth_continue(struct auth_request *auth_request,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (parse_cram_response(request, data, data_size, &error)) {
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen if (auth_request_set_username(auth_request, request->username,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_info(auth_request, "cram-md5", "%s", error);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenmech_cram_md5_auth_initial(struct auth_request *auth_request,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request->challenge = p_strdup(request->pool, get_cram_challenge());
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen request->challenge, strlen(request->challenge));
4ac5448461b63de9637de839fbc611a3d503287cTimo Sirainenstatic struct auth_request *mech_cram_md5_auth_new(void)
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen pool = pool_alloconly_create("cram_md5_auth_request", 2048);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request = p_new(pool, struct cram_auth_request, 1);