s4:auth/ntlmssp: let get_challenge() return a NTSTATUS and fill a stack buffer
[ira/wip.git] / source4 / auth / ntlmssp / ntlmssp_server.c
index 52c027baac4354639ecabed197e629f539da58ab..ae199700441c8c94d8b2161898f26392ab187cfb 100644 (file)
 */
 
 #include "includes.h"
+#include "system/network.h"
+#include "lib/tsocket/tsocket.h"
 #include "auth/ntlmssp/ntlmssp.h"
-#include "auth/ntlmssp/msrpc_parse.h"
-#include "lib/crypto/crypto.h"
-#include "system/filesys.h"
-#include "libcli/auth/libcli_auth.h"
-#include "auth/credentials/credentials.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "../lib/crypto/crypto.h"
 #include "auth/gensec/gensec.h"
 #include "auth/auth.h"
 #include "param/param.h"
@@ -91,7 +90,7 @@ static const char *ntlmssp_target_name(struct gensec_ntlmssp_state *gensec_ntlms
                                       uint32_t neg_flags, uint32_t *chal_flags) 
 {
        if (neg_flags & NTLMSSP_REQUEST_TARGET) {
-               *chal_flags |= NTLMSSP_CHAL_TARGET_INFO;
+               *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
                *chal_flags |= NTLMSSP_REQUEST_TARGET;
                if (gensec_ntlmssp_state->server_role == ROLE_STANDALONE) {
                        *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
@@ -123,12 +122,11 @@ NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security,
 {
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
        DATA_BLOB struct_blob;
-       char dnsname[MAXHOSTNAMELEN], dnsdomname[MAXHOSTNAMELEN];
-       const char *p;
        uint32_t neg_flags = 0;
        uint32_t ntlmssp_command, chal_flags;
-       const uint8_t *cryptkey;
+       uint8_t cryptkey[8];
        const char *target_name;
+       NTSTATUS status;
 
        /* parse the NTLMSSP packet */
 #if 0
@@ -136,7 +134,8 @@ NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security,
 #endif
 
        if (in.length) {
-               if ((in.length < 16) || !msrpc_parse(out_mem_ctx, &in, "Cdd",
+               if ((in.length < 16) || !msrpc_parse(out_mem_ctx, 
+                                                        &in, "Cdd",
                                                         "NTLMSSP",
                                                         &ntlmssp_command,
                                                         &neg_flags)) {
@@ -152,7 +151,12 @@ NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security,
        ntlmssp_handle_neg_flags(gensec_ntlmssp_state, neg_flags, gensec_ntlmssp_state->allow_lm_key);
 
        /* Ask our caller what challenge they would like in the packet */
-       cryptkey = gensec_ntlmssp_state->get_challenge(gensec_ntlmssp_state);
+       status = gensec_ntlmssp_state->get_challenge(gensec_ntlmssp_state, cryptkey);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("ntlmssp_server_negotiate: backend doesn't give a challenge: %s\n",
+                         nt_errstr(status)));
+               return status;
+       }
 
        /* Check if we may set the challenge */
        if (!gensec_ntlmssp_state->may_set_challenge(gensec_ntlmssp_state)) {
@@ -175,25 +179,23 @@ NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security,
        gensec_ntlmssp_state->chal = data_blob_talloc(gensec_ntlmssp_state, cryptkey, 8);
        gensec_ntlmssp_state->internal_chal = data_blob_talloc(gensec_ntlmssp_state, cryptkey, 8);
 
-       dnsname[0] = '\0';
-       if (gethostname(dnsname, sizeof(dnsname)) == -1) {
-               DEBUG(0,("gethostname failed\n"));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       /* This should be a 'netbios domain -> DNS domain' mapping */
-       p = strchr(dnsname, '.');
-       if (p != NULL) {
-               safe_strcpy(dnsdomname, p+1, sizeof(dnsdomname));
-               strlower_m(dnsdomname);
-       } else {
-               dnsdomname[0] = '\0';
-       }
-       
        /* This creates the 'blob' of names that appears at the end of the packet */
-       if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) 
-       {
+       if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
+               char dnsdomname[MAXHOSTNAMELEN], dnsname[MAXHOSTNAMELEN];
                const char *target_name_dns = "";
+
+               /* Find out the DNS domain name */
+               dnsdomname[0] = '\0';
+               safe_strcpy(dnsdomname, lp_dnsdomain(gensec_security->settings->lp_ctx), sizeof(dnsdomname) - 1);
+
+               /* Find out the DNS host name */
+               safe_strcpy(dnsname, gensec_ntlmssp_state->server_name, sizeof(dnsname) - 1);
+               if (dnsdomname[0] != '\0') {
+                       safe_strcat(dnsname, ".", sizeof(dnsname) - 1);
+                       safe_strcat(dnsname, dnsdomname, sizeof(dnsname) - 1);
+               }
+               strlower_m(dnsname);
+
                if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) {
                        target_name_dns = dnsdomname;
                } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) {
@@ -202,17 +204,17 @@ NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security,
 
                msrpc_gen(out_mem_ctx, 
                          &struct_blob, "aaaaa",
-                         NTLMSSP_NAME_TYPE_DOMAIN, target_name,
-                         NTLMSSP_NAME_TYPE_SERVER, gensec_ntlmssp_state->server_name,
-                         NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname,
-                         NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname,
-                         0, "");
+                         MsvAvNbDomainName, target_name,
+                         MsvAvNbComputerName, gensec_ntlmssp_state->server_name,
+                         MsvAvDnsDomainName, dnsdomname,
+                         MsvAvDnsComputerName, dnsname,
+                         MsvAvEOL, "");
        } else {
                struct_blob = data_blob(NULL, 0);
        }
 
        {
-               /* Marshel the packet in the right format, be it unicode or ASCII */
+               /* Marshal the packet in the right format, be it unicode or ASCII */
                const char *gen_string;
                if (gensec_ntlmssp_state->unicode) {
                        gen_string = "CdUdbddB";
@@ -455,7 +457,7 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
                }
 
        } else if (user_session_key && user_session_key->data) {
-               session_key = *user_session_key;
+               session_key = data_blob_talloc(gensec_ntlmssp_state, user_session_key->data, user_session_key->length);
                DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
                dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
 
@@ -464,7 +466,7 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
 
        } else if (lm_session_key && lm_session_key->data) {
                /* Very weird to have LM key, but no user session key, but anyway.. */
-               session_key = *lm_session_key;
+               session_key = data_blob_talloc(gensec_ntlmssp_state, lm_session_key->data, lm_session_key->length);
                DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
                dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
 
@@ -504,14 +506,12 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
                                                                      gensec_ntlmssp_state->encrypted_session_key.length);
                        dump_data_pw("KEY_EXCH session key:\n", gensec_ntlmssp_state->encrypted_session_key.data, 
                                     gensec_ntlmssp_state->encrypted_session_key.length);
+                       talloc_free(session_key.data);
                }
        } else {
                gensec_ntlmssp_state->session_key = session_key;
        }
 
-       /* keep the session key around on the new context */
-       talloc_steal(gensec_ntlmssp_state, session_key.data);
-
        if ((gensec_security->want_features & GENSEC_FEATURE_SIGN)
            || (gensec_security->want_features & GENSEC_FEATURE_SEAL)) {
                nt_status = ntlmssp_sign_init(gensec_ntlmssp_state);
@@ -599,17 +599,19 @@ NTSTATUS ntlmssp_server_auth(struct gensec_security *gensec_security,
  * @return an 8 byte random challenge
  */
 
-static const uint8_t *auth_ntlmssp_get_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state)
+static NTSTATUS auth_ntlmssp_get_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state,
+                                          uint8_t chal[8])
 {
        NTSTATUS status;
-       const uint8_t *chal;
 
-       status = auth_get_challenge(gensec_ntlmssp_state->auth_context, &chal);
+       status = gensec_ntlmssp_state->auth_context->get_challenge(gensec_ntlmssp_state->auth_context, chal);
        if (!NT_STATUS_IS_OK(status)) {
-               return NULL;
+               DEBUG(1, ("auth_ntlmssp_get_challenge: failed to get challenge: %s\n",
+                       nt_errstr(status)));
+               return status;
        }
 
-       return chal;
+       return NT_STATUS_OK;
 }
 
 /**
@@ -619,7 +621,7 @@ static const uint8_t *auth_ntlmssp_get_challenge(const struct gensec_ntlmssp_sta
  */
 static bool auth_ntlmssp_may_set_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state)
 {
-       return auth_challenge_may_be_modified(gensec_ntlmssp_state->auth_context);
+       return gensec_ntlmssp_state->auth_context->challenge_may_be_modified(gensec_ntlmssp_state->auth_context);
 }
 
 /**
@@ -638,7 +640,9 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct gensec_ntlmssp_state *gensec_n
 
        chal = challenge->data;
 
-       nt_status = auth_context_set_challenge(auth_context, chal, "NTLMSSP callback (NTLM2)");
+       nt_status = gensec_ntlmssp_state->auth_context->set_challenge(auth_context, 
+                                                                     chal, 
+                                                                     "NTLMSSP callback (NTLM2)");
 
        return nt_status;
 }
@@ -665,7 +669,7 @@ static NTSTATUS auth_ntlmssp_check_password(struct gensec_ntlmssp_state *gensec_
        user_info->client.account_name = gensec_ntlmssp_state->user;
        user_info->client.domain_name = gensec_ntlmssp_state->domain;
        user_info->workstation_name = gensec_ntlmssp_state->workstation;
-       user_info->remote_host = gensec_get_peer_addr(gensec_ntlmssp_state->gensec_security);
+       user_info->remote_host = gensec_get_remote_address(gensec_ntlmssp_state->gensec_security);
 
        user_info->password_state = AUTH_PASSWORD_RESPONSE;
        user_info->password.response.lanman = gensec_ntlmssp_state->lm_resp;
@@ -673,8 +677,10 @@ static NTSTATUS auth_ntlmssp_check_password(struct gensec_ntlmssp_state *gensec_
        user_info->password.response.nt = gensec_ntlmssp_state->nt_resp;
        user_info->password.response.nt.data = talloc_steal(user_info, gensec_ntlmssp_state->nt_resp.data);
 
-       nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, mem_ctx,
-                                       user_info, &gensec_ntlmssp_state->server_info);
+       nt_status = gensec_ntlmssp_state->auth_context->check_password(gensec_ntlmssp_state->auth_context, 
+                                                                      mem_ctx,
+                                                                      user_info, 
+                                                                      &gensec_ntlmssp_state->server_info);
        talloc_free(user_info);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
@@ -717,7 +723,7 @@ NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
        NTSTATUS nt_status;
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
-       nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
+       nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_security->event_ctx, gensec_security->settings->lp_ctx, gensec_ntlmssp_state->server_info, session_info);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
        (*session_info)->session_key = data_blob_talloc(*session_info, 
@@ -744,41 +750,41 @@ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
        gensec_ntlmssp_state->role = NTLMSSP_SERVER;
 
        gensec_ntlmssp_state->workstation = NULL;
-       gensec_ntlmssp_state->server_name = lp_netbios_name(gensec_security->lp_ctx);
+       gensec_ntlmssp_state->server_name = lp_netbios_name(gensec_security->settings->lp_ctx);
 
-       gensec_ntlmssp_state->domain = lp_workgroup(gensec_security->lp_ctx);
+       gensec_ntlmssp_state->domain = lp_workgroup(gensec_security->settings->lp_ctx);
 
        gensec_ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
 
-       gensec_ntlmssp_state->allow_lm_key = (lp_lanman_auth(gensec_security->lp_ctx) 
-                                         && lp_parm_bool(gensec_security->lp_ctx, NULL, "ntlmssp_server", "allow_lm_key", false));
+       gensec_ntlmssp_state->allow_lm_key = (lp_lanman_auth(gensec_security->settings->lp_ctx) 
+                                         && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false));
 
        gensec_ntlmssp_state->server_multiple_authentications = false;
        
        gensec_ntlmssp_state->neg_flags = 
-               NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_UNKNOWN_02000000;
+               NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION;
 
        gensec_ntlmssp_state->lm_resp = data_blob(NULL, 0);
        gensec_ntlmssp_state->nt_resp = data_blob(NULL, 0);
        gensec_ntlmssp_state->encrypted_session_key = data_blob(NULL, 0);
 
-       if (lp_parm_bool(gensec_security->lp_ctx, NULL, "ntlmssp_server", "128bit", true)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;               
        }
 
-       if (lp_parm_bool(gensec_security->lp_ctx, NULL, "ntlmssp_server", "56bit", true)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;                
        }
 
-       if (lp_parm_bool(gensec_security->lp_ctx, NULL, "ntlmssp_server", "keyexchange", true)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;          
        }
 
-       if (lp_parm_bool(gensec_security->lp_ctx, NULL, "ntlmssp_server", "alwayssign", true)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;               
        }
 
-       if (lp_parm_bool(gensec_security->lp_ctx, NULL, "ntlmssp_server", "ntlm2", true)) {
+       if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) {
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;             
        }
 
@@ -789,18 +795,13 @@ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
        }
 
-       nt_status = auth_context_create(gensec_ntlmssp_state, 
-                                       gensec_security->event_ctx,
-                                       gensec_security->msg_ctx,
-                                       gensec_security->lp_ctx,
-                                       &gensec_ntlmssp_state->auth_context);
-       NT_STATUS_NOT_OK_RETURN(nt_status);
+       gensec_ntlmssp_state->auth_context = gensec_security->auth_context;
 
        gensec_ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
        gensec_ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
        gensec_ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
        gensec_ntlmssp_state->check_password = auth_ntlmssp_check_password;
-       gensec_ntlmssp_state->server_role = lp_server_role(gensec_security->lp_ctx);
+       gensec_ntlmssp_state->server_role = lp_server_role(gensec_security->settings->lp_ctx);
 
        return NT_STATUS_OK;
 }