s4:s3compat Add implementation of kerberos_return_pac()
authorAndrew Bartlett <abartlet@samba.org>
Wed, 12 May 2010 21:50:10 +0000 (07:50 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 3 Jun 2010 01:14:05 +0000 (11:14 +1000)
This allows the winbindd from source3 to link in s3comapt, while using
the source4/ Kerberos code to handle the PAC collection and extraction.

Andrew Bartlett

source4/s3compat/s3compat_authenticate.c

index 407a7dc4fe22e1a4850d2a5e2e176b2622859326..b7378ef24a98460d21ccfe7031acfcf1a21fbbc8 100644 (file)
@@ -58,6 +58,11 @@ NTSTATUS s3compat_authenticate(TALLOC_CTX *mem_ctx, uint8_t chall[8], const stru
        return nt_status;
 }
 
+/* NOTE:  This interface implementation does not honour:
+ - realm
+ - time_offset
+ - use_replay_cache
+*/
 _PUBLIC_ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
                                    const char *realm,
                                    time_t time_offset,
@@ -96,7 +101,7 @@ _PUBLIC_ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
                                              s3compat_get_msg_ctx(),
                                              lp_ctx,
                                              server_credentials,
-                                             "cifs",
+                                             "host",
                                              &gensec_server_context);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(1, (__location__ "Failed to start server-side GENSEC for to validate a Kerberos ticket: %s\n", nt_errstr(nt_status)));
@@ -142,3 +147,101 @@ _PUBLIC_ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+/****************************************************************
+Given a username, password and other details, return the
+PAC_LOGON_INFO (the structure containing the important user
+information such as groups).
+****************************************************************/
+
+_PUBLIC_ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx,
+                                     const char *name,
+                                     const char *pass,
+                                     time_t time_offset,
+                                     time_t *expire_time,
+                                     time_t *renew_till_time,
+                                     const char *cache_name,
+                                     bool request_pac,
+                                     bool add_netbios_addr,
+                                     time_t renewable_time,
+                                     const char *impersonate_princ_s,
+                                     struct PAC_LOGON_INFO **logon_info)
+{
+       DATA_BLOB server_to_client, ticket, ap_rep, session_key;
+       struct cli_credentials *server_credentials, *client_credentials;
+       struct gensec_security *gensec_client_context;
+       struct loadparm_context *lp_ctx = s3compat_get_lp_ctx();
+       struct tevent_context *ev_ctx = s3compat_get_tevent_ctx();
+       const char *error_string;
+       char *principal;
+       NTSTATUS status;
+       int ret;
+
+        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+        NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+       
+       server_credentials = cli_credentials_init(tmp_ctx);
+       NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_credentials, tmp_ctx);
+       
+       cli_credentials_set_conf(server_credentials, lp_ctx);
+       status = cli_credentials_set_machine_account(server_credentials, lp_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("Failed to obtain server credentials, can not validate a Kerberos ticket: %s\n", nt_errstr(status)));
+               talloc_free(tmp_ctx);
+               return status;
+       }
+
+       client_credentials = cli_credentials_init(tmp_ctx);
+       NT_STATUS_HAVE_NO_MEMORY_AND_FREE(client_credentials, tmp_ctx);
+       
+       cli_credentials_set_conf(client_credentials, lp_ctx);
+       if (cache_name) {
+               ret = cli_credentials_set_ccache(client_credentials, ev_ctx, lp_ctx, cache_name, CRED_SPECIFIED, &error_string);
+               if (ret != 0) {
+                       DEBUG(2, ("Could not set credentialse cache to %s: %s", cache_name, error_string));
+                       talloc_free(tmp_ctx);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+       }
+
+       if (impersonate_princ_s) {
+               cli_credentials_set_impersonate_principal(client_credentials, impersonate_princ_s);
+       }
+       cli_credentials_set_principal(client_credentials, name, CRED_SPECIFIED);
+       cli_credentials_set_password(client_credentials, pass, CRED_SPECIFIED);
+
+       status = gensec_client_start(tmp_ctx, &gensec_client_context, ev_ctx, 
+                                    lp_gensec_settings(tmp_ctx, lp_ctx));
+       NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
+       
+       status = gensec_set_target_principal(gensec_client_context, cli_credentials_get_principal(server_credentials, tmp_ctx));
+       NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
+       
+       status = gensec_set_credentials(gensec_client_context, client_credentials);
+       NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
+       
+       status = gensec_start_mech_by_name(gensec_client_context, "krb5");
+       NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
+       
+       server_to_client = data_blob(NULL, 0);
+       
+       status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &ticket);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
+               if (NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("gensec_update for krb5 returned NT_STATUS_OK, should return NT_STATUS_MORE_PROCESSING_REQUIRED every time"));
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+                       DEBUG(0, ("gensec_update for krb5 returned NT_STATUS_INVALID_PARAMETER, perhaps we can't reach the KDC?"));
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               return status;
+       }
+       
+       status = ads_verify_ticket(mem_ctx, lp_realm(lp_ctx),
+                                  0, &ticket,
+                                  &principal,
+                                  logon_info, 
+                                  &ap_rep, &session_key, false);
+       talloc_free(tmp_ctx);
+       return status;
+}