s3: Fix Coverity ID 2304: FORWARD_NULL
[samba.git] / source3 / smbd / sesssetup.c
index c9b5b8cb878f4f7ae947ba75e7679b0be694b6ae..c5d44c6185e1de8e620012553b4db34ec35339a8 100644 (file)
 */
 
 #include "includes.h"
+#include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "../libcli/auth/spnego.h"
 #include "../libcli/auth/ntlmssp.h"
 #include "ntlmssp_wrap.h"
-#include "librpc/gen_ndr/messaging.h"
 #include "../librpc/gen_ndr/krb5pac.h"
 #include "libads/kerberos_proto.h"
+#include "../lib/util/asn1.h"
+#include "auth.h"
+#include "messages.h"
 
 /* For split krb5 SPNEGO blobs. */
 struct pending_auth_data {
@@ -141,14 +144,12 @@ static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_in
        struct auth_usersupplied_info *user_info = NULL;
 
        NTSTATUS nt_status;
-       unsigned char chal[8];
-
-       ZERO_STRUCT(chal);
+       static unsigned char chal[8] = { 0, };
 
        DEBUG(3,("Got anonymous request\n"));
 
-       if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
-                                       chal))) {
+       nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
@@ -368,85 +369,17 @@ static void reply_spnego_kerberos(struct smb_request *req,
        /* reload services so that the new %U is taken into account */
        reload_services(sconn->msg_ctx, sconn->sock, True);
 
-       if (map_domainuser_to_guest) {
-               ret = make_server_info_guest(NULL, &server_info);
-               if (!NT_STATUS_IS_OK(ret)) {
-                       DEBUG(1, ("make_server_info_guest failed: %s!\n",
-                                nt_errstr(ret)));
-                       data_blob_free(&ap_rep);
-                       data_blob_free(&session_key);
-                       TALLOC_FREE(mem_ctx);
-                       reply_nterror(req, nt_status_squash(ret));
-                       return;
-               }
-       } else if (logon_info) {
-               /* pass the unmapped username here since map_username()
-                  will be called again from inside make_server_info_info3() */
-
-               ret = make_server_info_info3(mem_ctx, user, domain,
-                                            &server_info, &logon_info->info3);
-               if (!NT_STATUS_IS_OK(ret)) {
-                       DEBUG(1,("make_server_info_info3 failed: %s!\n",
-                                nt_errstr(ret)));
-                       data_blob_free(&ap_rep);
-                       data_blob_free(&session_key);
-                       TALLOC_FREE(mem_ctx);
-                       reply_nterror(req, nt_status_squash(ret));
-                       return;
-               }
-
-       } else {
-               /*
-                * We didn't get a PAC, we have to make up the user
-                * ourselves. Try to ask the pdb backend to provide
-                * SID consistency with ntlmssp session setup
-                */
-               struct samu *sampass;
-
-               sampass = samu_new(talloc_tos());
-               if (sampass == NULL) {
-                       ret = NT_STATUS_NO_MEMORY;
-                       data_blob_free(&ap_rep);
-                       data_blob_free(&session_key);
-                       TALLOC_FREE(mem_ctx);
-                       reply_nterror(req, nt_status_squash(ret));
-                       return;
-               }
-
-               if (pdb_getsampwnam(sampass, real_username)) {
-                       DEBUG(10, ("found user %s in passdb, calling "
-                                  "make_server_info_sam\n", real_username));
-                       ret = make_server_info_sam(&server_info, sampass);
-                       TALLOC_FREE(sampass);
-               } else {
-                       /*
-                        * User not in passdb, make it up artificially
-                        */
-                       TALLOC_FREE(sampass);
-                       DEBUG(10, ("didn't find user %s in passdb, calling "
-                                  "make_server_info_pw\n", real_username));
-                       ret = make_server_info_pw(&server_info, real_username,
-                                                 pw);
-               }
-
-               if ( !NT_STATUS_IS_OK(ret) ) {
-                       DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
-                                nt_errstr(ret)));
-                       data_blob_free(&ap_rep);
-                       data_blob_free(&session_key);
-                       TALLOC_FREE(mem_ctx);
-                       reply_nterror(req, nt_status_squash(ret));
-                       return;
-               }
-
-               /* make_server_info_pw does not set the domain. Without this
-                * we end up with the local netbios name in substitutions for
-                * %D. */
-
-               if (server_info->info3 != NULL) {
-                       server_info->info3->base.domain.string =
-                               talloc_strdup(server_info->info3, domain);
-               }
+       ret = make_server_info_krb5(mem_ctx,
+                                   user, domain, real_username, pw,
+                                   logon_info, map_domainuser_to_guest,
+                                   &server_info);
+       if (!NT_STATUS_IS_OK(ret)) {
+               DEBUG(1, ("make_server_info_krb5 failed!\n"));
+               data_blob_free(&ap_rep);
+               data_blob_free(&session_key);
+               TALLOC_FREE(mem_ctx);
+               reply_nterror(req, nt_status_squash(ret));
+               return;
        }
 
        server_info->nss_token |= username_was_mapped;
@@ -454,7 +387,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
        /* we need to build the token for the user. make_server_info_guest()
           already does this */
 
-       if ( !server_info->ptok ) {
+       if ( !server_info->security_token ) {
                ret = create_local_token( server_info );
                if ( !NT_STATUS_IS_OK(ret) ) {
                        DEBUG(10,("failed to create local token: %s\n",
@@ -473,6 +406,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
        }
 
        data_blob_free(&server_info->user_session_key);
+       /* Set the kerberos-derived session key onto the server_info */
        server_info->user_session_key = session_key;
        talloc_steal(server_info, session_key.data);
 
@@ -543,19 +477,19 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 {
        bool do_invalidate = true;
        DATA_BLOB response;
-       struct auth_serversupplied_info *server_info = NULL;
+       struct auth_serversupplied_info *session_info = NULL;
        struct smbd_server_connection *sconn = req->sconn;
 
        if (NT_STATUS_IS_OK(nt_status)) {
-               nt_status = auth_ntlmssp_steal_server_info(talloc_tos(),
-                                       (*auth_ntlmssp_state), &server_info);
+               nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
+                                       (*auth_ntlmssp_state), &session_info);
        } else {
-               /* Note that this server_info won't have a session
+               /* Note that this session_info won't have a session
                 * key.  But for map to guest, that's exactly the right
                 * thing - we can't reasonably guess the key the
                 * client wants, as the password was wrong */
                nt_status = do_map_to_guest(nt_status,
-                                           &server_info,
+                                           &session_info,
                                            auth_ntlmssp_get_username(*auth_ntlmssp_state),
                                            auth_ntlmssp_get_domain(*auth_ntlmssp_state));
        }
@@ -574,7 +508,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 
                /* register_existing_vuid keeps the server info */
                if (register_existing_vuid(sconn, vuid,
-                                          server_info, nullblob,
+                                          session_info, nullblob,
                                           auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
                                           vuid) {
                        /* The problem is, *auth_ntlmssp_state points
@@ -591,7 +525,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 
                SSVAL(req->outbuf, smb_vwv3, 0);
 
-               if (server_info->guest) {
+               if (session_info->guest) {
                        SSVAL(req->outbuf,smb_vwv2,1);
                }
        }
@@ -642,7 +576,8 @@ NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
        *kerb_mechOID = NULL;
 
        /* parse out the OIDs and the first sec blob */
-       if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out)) {
+       if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
+                       (OIDs[0] == NULL)) {
                return NT_STATUS_LOGON_FAILURE;
        }
 
@@ -738,9 +673,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
        }
 #endif
 
-       if (*auth_ntlmssp_state) {
-               TALLOC_FREE(*auth_ntlmssp_state);
-       }
+       TALLOC_FREE(*auth_ntlmssp_state);
 
        if (kerb_mech) {
                data_blob_free(&secblob);
@@ -1163,6 +1096,10 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
                } else {
                        ra_lanman_string( native_lanman );
                }
+       } else if ( ra_type == RA_VISTA ) {
+               if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
+                       set_remote_arch(RA_OSX);
+               }
        }
 
        /* Did we get a valid vuid ? */
@@ -1614,13 +1551,20 @@ void reply_sesssetup_and_X(struct smb_request *req)
        reload_services(sconn->msg_ctx, sconn->sock, True);
 
        if (lp_security() == SEC_SHARE) {
+               char *sub_user_mapped = NULL;
                /* In share level we should ignore any passwords */
 
                data_blob_free(&lm_resp);
                data_blob_free(&nt_resp);
                data_blob_clear_free(&plaintext_password);
 
-               map_username(sub_user);
+               (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
+               if (!sub_user_mapped) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBsesssetupX);
+                       return;
+               }
+               fstrcpy(sub_user, sub_user_mapped);
                add_session_user(sconn, sub_user);
                add_session_workgroup(sconn, domain);
                /* Then force it to null for the benfit of the code below */
@@ -1655,7 +1599,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                struct auth_context *plaintext_auth_context = NULL;
 
                nt_status = make_auth_context_subsystem(
-                               &plaintext_auth_context);
+                       talloc_tos(), &plaintext_auth_context);
 
                if (NT_STATUS_IS_OK(nt_status)) {
                        uint8_t chal[8];
@@ -1704,7 +1648,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                return;
        }
 
-       if (!server_info->ptok) {
+       if (!server_info->security_token) {
                nt_status = create_local_token(server_info);
 
                if (!NT_STATUS_IS_OK(nt_status)) {