mech-cram-md5.c revision ab5c28d0976c4e89d503f1fe9b1568f9a125e176
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
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)
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(&request->auth_request, AUTH_SUBSYS_MECH,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen "invalid credentials length");
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz hmac_update(&ctx, request->challenge, strlen(request->challenge));
a7790b4f44c743a821fa065084fd6286767bfa8aTimo Sirainen response_hex = binary_to_hex(digest, sizeof(digest));
ace06232cfa0e99ecca1040e8553b3216d025768Timo Sirainen if (!mem_equals_timing_safe(response_hex, request->response, sizeof(digest)*2)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(&request->auth_request, AUTH_SUBSYS_MECH,
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,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH, "%s", error);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenmech_cram_md5_auth_initial(struct auth_request *auth_request,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request->challenge = p_strdup(request->pool, get_cram_challenge());
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply_continue(auth_request, request->challenge,
4ac5448461b63de9637de839fbc611a3d503287cTimo Sirainenstatic struct auth_request *mech_cram_md5_auth_new(void)
1b81b28b2e7856748cffd7d01052a944b6c80b23Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"cram_md5_auth_request", 2048);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request = p_new(pool, struct cram_auth_request, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .flags = MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,