s3:netlookup: make use of cli_credentials_init_anon()
[bbaumbach/samba-autobuild/.git] / source3 / utils / ntlm_auth.c
index aeae460ce8d8247727a721dfc99a58853e0223e7..7f8d2688978d7d4a644c636a56f3e98b420761b7 100644 (file)
@@ -47,6 +47,7 @@
 #include "lib/param/loadparm.h"
 #include "lib/util/base64.h"
 #include "cmdline_contexts.h"
+#include "lib/util/tevent_ntstatus.h"
 
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
@@ -940,91 +941,246 @@ static NTSTATUS ntlm_auth_set_challenge(struct auth4_context *auth_ctx, const ui
  * Return the session keys used on the connection.
  */
 
-static NTSTATUS winbind_pw_check(struct auth4_context *auth4_context,
-                                TALLOC_CTX *mem_ctx,
-                                const struct auth_usersupplied_info *user_info,
-                                uint8_t *pauthoritative,
-                                void **server_returned_info,
-                                DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
+struct winbind_pw_check_state {
+       uint8_t authoritative;
+       void *server_info;
+       DATA_BLOB nt_session_key;
+       DATA_BLOB lm_session_key;
+};
+
+static struct tevent_req *winbind_pw_check_send(
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct auth4_context *auth4_context,
+       const struct auth_usersupplied_info *user_info)
 {
+       struct tevent_req *req = NULL;
+       struct winbind_pw_check_state *state = NULL;
        NTSTATUS nt_status;
        char *error_string = NULL;
        uint8_t lm_key[8];
        uint8_t user_sess_key[16];
        char *unix_name = NULL;
 
-       nt_status = contact_winbind_auth_crap(user_info->client.account_name, user_info->client.domain_name,
-                                             user_info->workstation_name,
-                                             &auth4_context->challenge.data,
-                                             &user_info->password.response.lanman,
-                                             &user_info->password.response.nt,
-                                             WBFLAG_PAM_LMKEY | WBFLAG_PAM_USER_SESSION_KEY | WBFLAG_PAM_UNIX_NAME,
-                                             0,
-                                             lm_key, user_sess_key,
-                                             pauthoritative,
-                                             &error_string, &unix_name);
-
-       if (NT_STATUS_IS_OK(nt_status)) {
-               if (!all_zero(lm_key, 8)) {
-                       *lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
-                       memcpy(lm_session_key->data, lm_key, 8);
-                       memset(lm_session_key->data+8, '\0', 8);
+       req = tevent_req_create(
+               mem_ctx, &state, struct winbind_pw_check_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       nt_status = contact_winbind_auth_crap(
+               user_info->client.account_name,
+               user_info->client.domain_name,
+               user_info->workstation_name,
+               &auth4_context->challenge.data,
+               &user_info->password.response.lanman,
+               &user_info->password.response.nt,
+               WBFLAG_PAM_LMKEY |
+               WBFLAG_PAM_USER_SESSION_KEY |
+               WBFLAG_PAM_UNIX_NAME,
+               0,
+               lm_key, user_sess_key,
+               &state->authoritative,
+               &error_string,
+               &unix_name);
+
+       if (tevent_req_nterror(req, nt_status)) {
+               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
+                       DBG_ERR("Login for user [%s]\\[%s]@[%s] failed due "
+                               "to [%s]\n",
+                               user_info->client.domain_name,
+                               user_info->client.account_name,
+                               user_info->workstation_name,
+                               error_string ?
+                               error_string :
+                               "unknown error (NULL)");
+               } else {
+                       DBG_NOTICE("Login for user [%s]\\[%s]@[%s] failed due "
+                                  "to [%s]\n",
+                                  user_info->client.domain_name,
+                                  user_info->client.account_name,
+                                  user_info->workstation_name,
+                                  error_string ?
+                                  error_string :
+                                  "unknown error (NULL)");
                }
+               goto done;
+       }
 
-               if (!all_zero(user_sess_key, 16)) {
-                       *session_key = data_blob_talloc(mem_ctx, user_sess_key, 16);
+       if (!all_zero(lm_key, 8)) {
+               state->lm_session_key = data_blob_talloc(state, NULL, 16);
+               if (tevent_req_nomem(state->lm_session_key.data, req)) {
+                       goto done;
                }
-               *server_returned_info = talloc_strdup(mem_ctx,
-                                                     unix_name);
-       } else {
-               DEBUG(NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED) ? 0 : 3, 
-                     ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n",
-                      user_info->client.domain_name, user_info->client.account_name,
-                      user_info->workstation_name,
-                      error_string ? error_string : "unknown error (NULL)"));
+               memcpy(state->lm_session_key.data, lm_key, 8);
+               memset(state->lm_session_key.data+8, '\0', 8);
+       }
+       if (!all_zero(user_sess_key, 16)) {
+               state->nt_session_key = data_blob_talloc(
+                       state, user_sess_key, 16);
+               if (tevent_req_nomem(state->nt_session_key.data, req)) {
+                       goto done;
+               }
+       }
+       state->server_info = talloc_strdup(state, unix_name);
+       if (tevent_req_nomem(state->server_info, req)) {
+               goto done;
        }
+       tevent_req_done(req);
 
+done:
        SAFE_FREE(error_string);
        SAFE_FREE(unix_name);
-       return nt_status;
+       return tevent_req_post(req, ev);
 }
 
-static NTSTATUS local_pw_check(struct auth4_context *auth4_context,
-                               TALLOC_CTX *mem_ctx,
-                               const struct auth_usersupplied_info *user_info,
-                               uint8_t *pauthoritative,
-                               void **server_returned_info,
-                               DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
+static NTSTATUS winbind_pw_check_recv(struct tevent_req *req,
+                                     TALLOC_CTX *mem_ctx,
+                                     uint8_t *pauthoritative,
+                                     void **server_returned_info,
+                                     DATA_BLOB *nt_session_key,
+                                     DATA_BLOB *lm_session_key)
 {
-       NTSTATUS nt_status;
+       struct winbind_pw_check_state *state = tevent_req_data(
+               req, struct winbind_pw_check_state);
+       NTSTATUS status;
+
+       if (pauthoritative != NULL) {
+               *pauthoritative = state->authoritative;
+       }
+
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
+       }
+
+       if (server_returned_info != NULL) {
+               *server_returned_info = talloc_move(
+                       mem_ctx, &state->server_info);
+       }
+       if (nt_session_key != NULL) {
+               *nt_session_key = (DATA_BLOB) {
+                       .data = talloc_move(
+                               mem_ctx, &state->nt_session_key.data),
+                       .length = state->nt_session_key.length,
+               };
+       }
+       if (lm_session_key != NULL) {
+               *lm_session_key = (DATA_BLOB) {
+                       .data = talloc_move(
+                               mem_ctx, &state->lm_session_key.data),
+                       .length = state->lm_session_key.length,
+               };
+       }
+
+       return NT_STATUS_OK;
+}
+
+struct local_pw_check_state {
+       uint8_t authoritative;
+       void *server_info;
+       DATA_BLOB nt_session_key;
+       DATA_BLOB lm_session_key;
+};
+
+static struct tevent_req *local_pw_check_send(
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct auth4_context *auth4_context,
+       const struct auth_usersupplied_info *user_info)
+{
+       struct tevent_req *req = NULL;
+       struct local_pw_check_state *state = NULL;
        struct samr_Password lm_pw, nt_pw;
+       NTSTATUS nt_status;
+
+       req = tevent_req_create(
+               mem_ctx, &state, struct local_pw_check_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->authoritative = 1;
 
        nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash);
 
-       *pauthoritative = 1;
+       nt_status = ntlm_password_check(
+               state,
+               true,
+               NTLM_AUTH_ON,
+               0,
+               &auth4_context->challenge.data,
+               &user_info->password.response.lanman,
+               &user_info->password.response.nt,
+               user_info->client.account_name,
+               user_info->client.account_name,
+               user_info->client.domain_name,
+               &lm_pw,
+               &nt_pw,
+               &state->nt_session_key,
+               &state->lm_session_key);
+
+       if (tevent_req_nterror(req, nt_status)) {
+               DBG_NOTICE("Login for user [%s]\\[%s]@[%s] failed due to "
+                          "[%s]\n",
+                          user_info->client.domain_name,
+                          user_info->client.account_name,
+                          user_info->workstation_name,
+                          nt_errstr(nt_status));
+               return tevent_req_post(req, ev);
+       }
+
+       state->server_info = talloc_asprintf(
+               state,
+               "%s%c%s",
+               user_info->client.domain_name,
+               *lp_winbind_separator(),
+               user_info->client.account_name);
+       if (tevent_req_nomem(state->server_info, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_done(req);
+       return tevent_req_post(req, ev);
+}
 
-       nt_status = ntlm_password_check(mem_ctx,
-                                       true, NTLM_AUTH_ON, 0,
-                                       &auth4_context->challenge.data,
-                                       &user_info->password.response.lanman,
-                                       &user_info->password.response.nt,
-                                       user_info->client.account_name,
-                                       user_info->client.account_name,
-                                       user_info->client.domain_name,
-                                       &lm_pw, &nt_pw, session_key, lm_session_key);
-
-       if (NT_STATUS_IS_OK(nt_status)) {
-               *server_returned_info = talloc_asprintf(mem_ctx,
-                                                       "%s%c%s", user_info->client.domain_name,
-                                                       *lp_winbind_separator(),
-                                                       user_info->client.account_name);
-       } else {
-               DEBUG(3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n",
-                         user_info->client.domain_name, user_info->client.account_name,
-                         user_info->workstation_name,
-                         nt_errstr(nt_status)));
+static NTSTATUS local_pw_check_recv(struct tevent_req *req,
+                                   TALLOC_CTX *mem_ctx,
+                                   uint8_t *pauthoritative,
+                                   void **server_returned_info,
+                                   DATA_BLOB *nt_session_key,
+                                   DATA_BLOB *lm_session_key)
+{
+       struct local_pw_check_state *state = tevent_req_data(
+               req, struct local_pw_check_state);
+       NTSTATUS status;
+
+       if (pauthoritative != NULL) {
+               *pauthoritative = state->authoritative;
        }
-       return nt_status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
+       }
+
+       if (server_returned_info != NULL) {
+               *server_returned_info = talloc_move(
+                       mem_ctx, &state->server_info);
+       }
+       if (nt_session_key != NULL) {
+               *nt_session_key = (DATA_BLOB) {
+                       .data = talloc_move(
+                               mem_ctx, &state->nt_session_key.data),
+                       .length = state->nt_session_key.length,
+               };
+       }
+       if (lm_session_key != NULL) {
+               *lm_session_key = (DATA_BLOB) {
+                       .data = talloc_move(
+                               mem_ctx, &state->lm_session_key.data),
+                       .length = state->lm_session_key.length,
+               };
+       }
+
+       return NT_STATUS_OK;
 }
 
 static NTSTATUS ntlm_auth_prepare_gensec_client(TALLOC_CTX *mem_ctx,
@@ -1111,9 +1267,13 @@ static struct auth4_context *make_auth4_context_ntlm_auth(TALLOC_CTX *mem_ctx, b
        auth4_context->get_ntlm_challenge = ntlm_auth_get_challenge;
        auth4_context->set_ntlm_challenge = ntlm_auth_set_challenge;
        if (local_pw) {
-               auth4_context->check_ntlm_password = local_pw_check;
+               auth4_context->check_ntlm_password_send = local_pw_check_send;
+               auth4_context->check_ntlm_password_recv = local_pw_check_recv;
        } else {
-               auth4_context->check_ntlm_password = winbind_pw_check;
+               auth4_context->check_ntlm_password_send =
+                       winbind_pw_check_send;
+               auth4_context->check_ntlm_password_recv =
+                       winbind_pw_check_recv;
        }
        auth4_context->private_data = NULL;
        return auth4_context;
@@ -1315,9 +1475,20 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
        TALLOC_CTX *mem_ctx;
 
        mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx");
+       if (mem_ctx == NULL) {
+               printf("BH No Memory\n");
+               exit(1);
+       }
 
        if (*private1) {
-               state = (struct gensec_ntlm_state *)*private1;
+               state = talloc_get_type(*private1, struct gensec_ntlm_state);
+               if (state == NULL) {
+                       DBG_WARNING("*private1 is of type %s\n",
+                                   talloc_get_name(*private1));
+                       printf("BH *private1 is of type %s\n",
+                              talloc_get_name(*private1));
+                       exit(1);
+               }
        } else {
                state = talloc_zero(NULL, struct gensec_ntlm_state);
                if (!state) {