TODO: save PAC data in netsamlogon cache ? s3-auth Add auth hook for PAC parsing
authorAndrew Bartlett <abartlet@samba.org>
Sat, 31 Dec 2011 11:57:18 +0000 (22:57 +1100)
committerStefan Metzmacher <metze@samba.org>
Fri, 6 Jan 2012 12:37:06 +0000 (13:37 +0100)
This will allow gensec_gse to parse the PAC.

Andrew Bartlett

source3/auth/auth_generic.c

index d7108f5cbfd9b585ee381d5e0f222603cd702a7e..1f1aeb5aa028c4925ed63e425f04eef4d24a79df 100644 (file)
@@ -1,10 +1,11 @@
 /* 
    Unix SMB/Netbios implementation.
    Version 3.0
-   handle NLTMSSP, server side
+   handle GENSEC authentication, server side
 
    Copyright (C) Andrew Tridgell      2001
    Copyright (C) Andrew Bartlett 2001-2003,2011
+   Copyright (C) Simo Sorce 2010.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "../lib/tsocket/tsocket.h"
 #include "auth/gensec/gensec.h"
 #include "lib/param/param.h"
+#ifdef HAVE_KRB5
+#include "libcli/auth/krb5_wrap.h"
+#endif
+
+static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
+                                               TALLOC_CTX *mem_ctx,
+                                               struct smb_krb5_context *smb_krb5_context,
+                                               DATA_BLOB *pac_blob,
+                                               const char *princ_name,
+                                               const struct tsocket_address *remote_address,
+                                               uint32_t session_info_flags,
+                                               struct auth_session_info **session_info)
+{
+       TALLOC_CTX *tmp_ctx;
+       struct PAC_DATA *pac_data = NULL;
+       struct PAC_LOGON_INFO *logon_info = NULL;
+       unsigned int i;
+       bool is_mapped;
+       bool is_guest;
+       char *ntuser;
+       char *ntdomain;
+       char *username;
+       char *rhost;
+       struct passwd *pw;
+       NTSTATUS status;
+       int rc;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (pac_blob) {
+#ifdef HAVE_KRB5
+               status = kerberos_decode_pac(tmp_ctx,
+                                    *pac_blob,
+                                    NULL, NULL, NULL, NULL, 0, &pac_data);
+#else
+               status = NT_STATUS_ACCESS_DENIED;
+#endif
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto done;
+               }
+
+               /* get logon name and logon info */
+               for (i = 0; i < pac_data->num_buffers; i++) {
+                       struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
+
+                       switch (data_buf->type) {
+                       case PAC_TYPE_LOGON_INFO:
+                               if (!data_buf->info) {
+                                       break;
+                               }
+                               logon_info = data_buf->info->logon_info.info;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               if (!logon_info) {
+                       DEBUG(1, ("Invalid PAC data, missing logon info!\n"));
+                       status = NT_STATUS_NOT_FOUND;
+                       goto done;
+               }
+       }
+
+       rc = get_remote_hostname(remote_address,
+                                &rhost,
+                                tmp_ctx);
+       if (rc < 0) {
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+       if (strequal(rhost, "UNKNOWN")) {
+               rhost = tsocket_address_inet_addr_string(remote_address,
+                                                        tmp_ctx);
+               if (rhost == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+       }
+
+       status = get_user_from_kerberos_info(tmp_ctx, rhost,
+                                            princ_name, logon_info,
+                                            &is_mapped, &is_guest,
+                                            &ntuser, &ntdomain,
+                                            &username, &pw);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("Failed to map kerberos principal to system user "
+                         "(%s)\n", nt_errstr(status)));
+               status = NT_STATUS_ACCESS_DENIED;
+               goto done;
+       }
+
+       /* TODO: save PAC data in netsamlogon cache ? */
+
+       status = make_session_info_krb5(mem_ctx,
+                                       ntuser, ntdomain, username, pw,
+                                       logon_info, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
+                                       session_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n",
+                         nt_errstr(status)));
+               status = NT_STATUS_ACCESS_DENIED;
+               goto done;
+       }
+
+       DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n",
+                 ntuser, ntdomain, rhost));
+
+       status = NT_STATUS_OK;
+
+done:
+       TALLOC_FREE(tmp_ctx);
+       return status;
+}
 
 NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
                              const struct tsocket_address *remote_address,
@@ -54,6 +171,14 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
                struct gensec_settings *gensec_settings;
                struct loadparm_context *lp_ctx;
 
+               struct auth4_context *auth4_context = talloc_zero(tmp_ctx, struct auth4_context);
+               if (auth4_context == NULL) {
+                       DEBUG(10, ("failed to allocate auth4_context failed\n"));
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               auth4_context->generate_session_info_pac = auth3_generate_session_info_pac;
+
                lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_context());
                if (lp_ctx == NULL) {
                        DEBUG(10, ("loadparm_init_s3 failed\n"));
@@ -77,7 +202,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
                gensec_settings->backends[0] = &gensec_ntlmssp3_server_ops;
 
                nt_status = gensec_server_start(tmp_ctx, gensec_settings,
-                                               NULL, &gensec_security);
+                                               auth4_context, &gensec_security);
 
                if (!NT_STATUS_IS_OK(nt_status)) {
                        TALLOC_FREE(tmp_ctx);
@@ -85,6 +210,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
                }
                talloc_unlink(tmp_ctx, lp_ctx);
                talloc_unlink(tmp_ctx, gensec_settings);
+               talloc_unlink(tmp_ctx, auth4_context);
        }
 
        nt_status = gensec_set_remote_address(gensec_security,