Merge commit 'release-4-0-0alpha15' into master4-tmp
[amitay/samba.git] / source4 / ntvfs / cifs / vfs_cifs.c
index a8cd89a2ec6d27ad655b083ee4ad0e29c2db9400..91ca08d2de0b68b52d85058640bedb4c63b00e3f 100644 (file)
@@ -63,6 +63,8 @@ struct async_info {
        void *parms;
 };
 
+NTSTATUS ntvfs_cifs_init(void);
+
 #define CHECK_UPSTREAM_OPEN do { \
        if (! p->transport->socket->sock) { \
                req->async_states->state|=NTVFS_ASYNC_STATE_CLOSE; \
@@ -97,10 +99,12 @@ struct async_info {
 #define CIFS_DOMAIN            "cifs:domain"
 #define CIFS_SHARE             "cifs:share"
 #define CIFS_USE_MACHINE_ACCT  "cifs:use-machine-account"
+#define CIFS_USE_S4U2PROXY     "cifs:use-s4u2proxy"
 #define CIFS_MAP_GENERIC       "cifs:map-generic"
 #define CIFS_MAP_TRANS2                "cifs:map-trans2"
 
 #define CIFS_USE_MACHINE_ACCT_DEFAULT  false
+#define CIFS_USE_S4U2PROXY_DEFAULT     false
 #define CIFS_MAP_GENERIC_DEFAULT       false
 #define CIFS_MAP_TRANS2_DEFAULT                true
 
@@ -148,6 +152,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
 
        struct cli_credentials *credentials;
        bool machine_account;
+       bool s4u2proxy;
        const char* sharename;
 
        switch (tcon->generic.level) {
@@ -185,6 +190,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
        }
 
        machine_account = share_bool_option(scfg, CIFS_USE_MACHINE_ACCT, CIFS_USE_MACHINE_ACCT_DEFAULT);
+       s4u2proxy = share_bool_option(scfg, CIFS_USE_S4U2PROXY, CIFS_USE_S4U2PROXY_DEFAULT);
 
        p = talloc_zero(ntvfs, struct cvfs_private);
        if (!p) {
@@ -224,9 +230,54 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
        } else if (req->session_info->credentials) {
                DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
                credentials = req->session_info->credentials;
+       } else if (s4u2proxy) {
+               struct ccache_container *ccc = NULL;
+               const char *err_str = NULL;
+               int ret;
+               char *impersonate_principal;
+               char *self_service;
+               char *target_service;
+
+               impersonate_principal = talloc_asprintf(req, "%s@%s",
+                                               req->session_info->info->account_name,
+                                               req->session_info->info->domain_name);
+
+               self_service = talloc_asprintf(req, "cifs/%s",
+                                              lpcfg_netbios_name(ntvfs->ctx->lp_ctx));
+
+               target_service = talloc_asprintf(req, "cifs/%s", host);
+
+               DEBUG(5, ("CIFS backend: Using S4U2Proxy credentials\n"));
+
+               credentials = cli_credentials_init(p);
+               cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
+               if (domain) {
+                       cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
+               }
+               status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
+               cli_credentials_set_impersonate_principal(credentials,
+                                                         impersonate_principal,
+                                                         self_service);
+               cli_credentials_set_target_service(credentials, target_service);
+               ret = cli_credentials_get_ccache(credentials,
+                                                ntvfs->ctx->event_ctx,
+                                                ntvfs->ctx->lp_ctx,
+                                                &ccc,
+                                                &err_str);
+               if (ret != 0) {
+                       status = NT_STATUS_CROSSREALM_DELEGATION_FAILURE;
+                       DEBUG(1,("S4U2Proxy: cli_credentials_get_ccache() gave: ret[%d] str[%s] - %s\n",
+                               ret, err_str, nt_errstr(status)));
+                       return status;
+               }
+
        } else {
                DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
-               return NT_STATUS_INVALID_PARAMETER;
+               return NT_STATUS_INTERNAL_ERROR;
        }
 
        /* connect to the server, using the smbd event context */