r21969: Start working on the gss-side of the server negotiation.
authorJeremy Allison <jra@samba.org>
Tue, 27 Mar 2007 00:50:53 +0000 (00:50 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:18:54 +0000 (12:18 -0500)
Jeremy.
(This used to be commit fbc569b530104679e47fe743963eb0c4384de6ae)

source3/include/client.h
source3/include/includes.h
source3/include/trans2.h
source3/libsmb/smb_seal.c
source3/smbd/negprot.c
source3/smbd/seal.c

index 817ab0d5402b31d4ae4b44c8c7b6e6d0331810cc..3185f05ac19b52fe8877b422ae5dfa1e850dd0ff 100644 (file)
@@ -81,13 +81,20 @@ struct rpc_pipe_client {
 /* Transport encryption state. */
 enum smb_trans_enc_type { SMB_TRANS_ENC_NTLM, SMB_TRANS_ENC_GSS };
 
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+struct smb_tran_enc_state_gss {
+       gss_ctx_id_t gss_ctx;
+       gss_cred_id_t creds;
+};
+#endif
+
 struct smb_trans_enc_state {
        enum smb_trans_enc_type smb_enc_type;
        BOOL enc_on;
        union {
                NTLMSSP_STATE *ntlmssp_state;
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
-               gss_ctx_id_t context_handle;
+               struct smb_tran_enc_state_gss *gss_state;
 #endif
        } s;
 };
index c51da335a2d66add151dcf5510e022d5e92436fe..b4485ba30d1db59df2d9226698fcfabe0e9e3eb2 100644 (file)
@@ -1188,10 +1188,10 @@ krb5_error_code smb_krb5_mk_error(krb5_context context,
 
 /* Call for SMB transport encryption. */
 #if defined(HAVE_GSSAPI)
-NTSTATUS common_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf);
+NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf);
 #endif
 #if defined(HAVE_GSSAPI) 
-NTSTATUS common_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **buf_out);
+NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf, char **buf_out);
 #endif
 
 #endif /* HAVE_KRB5 */
index 32ea7d927f34c2a4979454916bce250e4bcd482e..5f7587d6ead59378dee98b08b0ea5c51cb7025a9 100644 (file)
@@ -530,6 +530,7 @@ findfirst/findnext is SMB_FIND_FILE_UNIX_INFO2.
 #define CIFS_UNIX_POSIX_PATHNAMES_CAP     0x10 /* Use POSIX pathnames on the wire. */
 #define CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP       0x20 /* We can cope with POSIX open/mkdir/unlink etc. */
 #define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP     0x40 /* We can do SPNEGO negotiations for encryption. */
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP   0x80 /* We *must* SPNEGO negotiations for encryption. */
 
 #define SMB_QUERY_POSIX_FS_INFO     0x201
 
index 95012d629eafaee07acb0fe137c44dae6f27ba5b..f0e79b404cf03f7d540366f21919e6d55406f7fb 100644 (file)
@@ -126,8 +126,9 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
 ******************************************************************************/
 
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- NTSTATUS common_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf)
+ NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
 {
+       gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
        OM_uint32 ret = 0;
        OM_uint32 minor = 0;
        int flags_got = 0;
@@ -142,7 +143,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
        in_buf.length = buf_len - 8;
 
        ret = gss_unwrap(&minor,
-                       context_handle,
+                       gss_ctx,
                        &in_buf,
                        &out_buf,
                        &flags_got,             /* did we get sign+seal ? */
@@ -178,8 +179,9 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
 ******************************************************************************/
 
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- NTSTATUS common_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **ppbuf_out)
+ NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf, char **ppbuf_out)
 {
+       gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
        OM_uint32 ret = 0;
        OM_uint32 minor = 0;
        int flags_got = 0;
@@ -196,7 +198,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
        in_buf.length = buf_len - 8;
 
        ret = gss_wrap(&minor,
-                       context_handle,
+                       gss_ctx,
                        True,                   /* we want sign+seal. */
                        GSS_C_QOP_DEFAULT,
                        &in_buf,
@@ -267,7 +269,7 @@ NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, cha
                        return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, buffer, buf_out);
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
                case SMB_TRANS_ENC_GSS:
-                       return common_gss_encrypt_buffer(es->s.context_handle, buffer, buf_out);
+                       return common_gss_encrypt_buffer(es->s.gss_state, buffer, buf_out);
 #endif
                default:
                        return NT_STATUS_NOT_SUPPORTED;
@@ -297,13 +299,29 @@ NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
                        return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
                case SMB_TRANS_ENC_GSS:
-                       return common_gss_decrypt_buffer(es->s.context_handle, buf);
+                       return common_gss_decrypt_buffer(es->s.gss_state, buf);
 #endif
                default:
                        return NT_STATUS_NOT_SUPPORTED;
        }
 }
 
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+/******************************************************************************
+ Shutdown a gss encryption state.
+******************************************************************************/
+
+static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
+{
+       OM_uint32 minor = 0;
+       struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
+
+       gss_release_cred(&minor, &gss_state->creds);
+       gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
+       SAFE_FREE(*pp_gss_state);
+}
+#endif
+
 /******************************************************************************
  Shutdown an encryption state.
 ******************************************************************************/
@@ -324,6 +342,9 @@ void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
        if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
                /* Free the gss context handle. */
+               if (es->s.gss_state) {
+                       common_free_gss_state(&es->s.gss_state);
+               }
        }
 #endif
        SAFE_FREE(es);
index bc7c75aab4cecbfaefefc861c6f235a1337ff9c1..e1df08579d27482102b8bc0e1dc75a40255591aa 100644 (file)
@@ -228,6 +228,10 @@ static DATA_BLOB negprot_spnego(void)
                name_to_fqdn(myname, global_myname());
                strlower_m(myname);
                asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
+               if (host_princ_s == NULL) {
+                       blob = data_blob(NULL, 0);
+                       return blob;
+               }
                blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
                SAFE_FREE(host_princ_s);
        }
index f95a982f606919acaecba47342a8543a48eb006b..fbb0eade523066c837f6649000df1978e5670540 100644 (file)
@@ -85,6 +85,85 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
        }
 }
 
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+
+/******************************************************************************
+ Import a name.
+******************************************************************************/
+
+static NTSTATUS get_gss_creds(const char *service,
+                               const char *name,
+                               gss_cred_usage_t cred_type,
+                               gss_cred_id_t *p_srv_cred)
+{
+       OM_uint32 ret;
+        OM_uint32 min;
+       gss_name_t srv_name;
+       gss_buffer_desc input_name;
+       char *host_princ_s = NULL;
+       NTSTATUS status = NT_STATUS_OK;
+
+       asprintf(&host_princ_s, "%s@%s", service, name);
+       if (host_princ_s == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       input_name.value = host_princ_s;
+       input_name.length = strlen(host_princ_s) + 1;
+
+       ret = gss_import_name(&min,
+                               &input_name,
+                               GSS_C_NT_HOSTBASED_SERVICE,
+                               &srv_name);
+
+       if (ret != GSS_S_COMPLETE) {
+               SAFE_FREE(host_princ_s);
+               return map_nt_error_from_gss(ret, min);
+       }
+
+       ret = gss_acquire_cred(&min,
+                               &srv_name,
+                               GSS_C_INDEFINITE,
+                               GSS_C_NULL_OID_SET,
+                               cred_type,
+                               p_srv_cred,
+                               NULL,
+                               NULL);
+
+       if (ret != GSS_S_COMPLETE) {
+               status = map_nt_error_from_gss(ret, min);
+       }
+
+       SAFE_FREE(host_princ_s);
+       gss_release_name(&min, &srv_name);
+       return status;
+}
+
+/******************************************************************************
+ Create a gss state.
+******************************************************************************/
+
+static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec)
+{
+       NTSTATUS status;
+       gss_cred_id_t srv_cred;
+       fstring fqdn;
+
+       name_to_fqdn(fqdn, global_myname());
+       strlower_m(fqdn);
+
+       status = get_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred);
+       if (!NT_STATUS_IS_OK(status)) {
+               status = get_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return nt_status_squash(status);
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+#endif
+
 /******************************************************************************
  Shutdown a server encryption context.
 ******************************************************************************/
@@ -148,6 +227,13 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
                case SMB_TRANS_ENC_GSS:
                        /* Acquire our credentials by calling gss_acquire_cred here. */
+                       {
+                               NTSTATUS status = make_auth_gss(ec);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       srv_free_encryption_context(&ec);
+                                       return NULL;
+                               }
+                       }
                        break;
 #endif
                default: