mech-ntlm.c revision 97c339398f1aba6f315b55a9b6ee6b020e33bea4
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * NTLM and NTLMv2 authentication mechanism.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * This program is free software; you can redistribute it and/or modify
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * it under the terms of the GNU Lesser General Public License as published
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * by the Free Software Foundation; either version 2 of the License, or
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * (at your option) any later version.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen /* requested: */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *challenge;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen /* received: */
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenstatic int lm_verify_credentials(struct ntlm_auth_request *request,
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen const unsigned char *client_response;
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen ntlmssp_buffer_length(request->response, lm_response);
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen client_response = ntlmssp_buffer_data(request->response, lm_response);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen i_error("ntlm(%s): passdb credentials' length is too small",
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen hash_buffer = buffer_create_data(request->auth_request.pool,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (hex_to_binary(credentials, hash_buffer) < 0) {
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen i_error("ntlm(%s): passdb credentials are not in hex",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ntlmssp_v1_response(hash, request->challenge, lm_response);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return memcmp(lm_response, client_response, LM_RESPONSE_SIZE) == 0;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenlm_credentials_callback(enum passdb_result result,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (lm_verify_credentials(request, credentials))
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenstatic int ntlm_verify_credentials(struct ntlm_auth_request *request,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen struct auth_request *auth_request = &request->auth_request;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *client_response;
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen ntlmssp_buffer_length(request->response, ntlm_response);
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen client_response = ntlmssp_buffer_data(request->response, ntlm_response);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen /* try LM authentication unless NTLM2 was negotiated */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen hash_buffer = buffer_create_data(auth_request->pool,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (response_length > NTLMSSP_RESPONSE_SIZE) {
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char ntlm_v2_response[NTLMSSP_V2_RESPONSE_SIZE];
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen const unsigned char *blob =
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * Authentication target == NULL because we are acting
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen * as a standalone server, not as NT domain member.
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return memcmp(ntlm_v2_response, client_response,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned char ntlm_response[NTLMSSP_RESPONSE_SIZE];
88c2db95c4a0f8f7986a63cd57cf4b6850d76543Timo Sirainen const unsigned char *client_lm_response =
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ntlmssp_buffer_data(request->response, lm_response);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenntlm_credentials_callback(enum passdb_result result,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen ret = ntlm_verify_credentials(request, credentials);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen /* NTLM credentials not found or didn't want to use them,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen try with LM credentials */
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen lookup_credentials(auth_request, PASSDB_CREDENTIALS_LANMAN,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenmech_ntlm_auth_continue(struct auth_request *auth_request,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (!ntlmssp_check_request(ntlm_request, data_size, &error)) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen message = ntlmssp_create_challenge(request->pool, ntlm_request,
1704aa6b56b6a97bab6e995bcf7170b0c6527291Timo Sirainen request->ntlm2_negotiated = flags & NTLMSSP_NEGOTIATE_NTLM2;
1704aa6b56b6a97bab6e995bcf7170b0c6527291Timo Sirainen request->unicode_negotiated = flags & NTLMSSP_NEGOTIATE_UNICODE;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (!ntlmssp_check_response(response, data_size, &error)) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request->response = p_malloc(request->pool, data_size);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen memcpy(request->response, response, data_size);
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen username = ntlmssp_t_str(request->response, user,
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen if (!auth_request_set_username(auth_request, username, &error)) {
b97514e470fc4c78f6f1ce4660f1e5aec559c3b4Timo Sirainenmech_ntlm_auth_initial(struct auth_request *request,
b97514e470fc4c78f6f1ce4660f1e5aec559c3b4Timo Sirainen callback(request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
b97514e470fc4c78f6f1ce4660f1e5aec559c3b4Timo Sirainen mech_ntlm_auth_continue(request, data, data_size, callback);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenmech_ntlm_auth_free(struct auth_request *request)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic struct auth_request *mech_ntlm_auth_new(void)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen pool = pool_alloconly_create("ntlm_auth_request", 256);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request = p_new(pool, struct ntlm_auth_request, 1);