r14542: Remove librpc, libndr and libnbt from includes.h
[bbaumbach/samba-autobuild/.git] / source4 / auth / gensec / gensec_krb5.c
index 36cfc49196eb367337550caa9bb00419c5e30ed1..9f5d38a01b4a34164c591c985651777533c72518 100644 (file)
 
 #include "includes.h"
 #include "system/kerberos.h"
-#include "system/time.h"
-#include "system/network.h"
 #include "auth/kerberos/kerberos.h"
-#include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "librpc/gen_ndr/krb5pac.h"
 #include "auth/auth.h"
+#include "lib/ldb/include/ldb.h"
+#include "auth/auth_sam.h"
+#include "system/network.h"
+#include "lib/socket/socket.h"
+#include "librpc/rpc/dcerpc.h"
 
 enum GENSEC_KRB5_STATE {
        GENSEC_KRB5_SERVER_START,
@@ -87,7 +90,9 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
        krb5_error_code ret;
        struct gensec_krb5_state *gensec_krb5_state;
        struct cli_credentials *creds;
-
+       const struct socket_address *my_addr, *peer_addr;
+       krb5_address my_krb5_addr, peer_krb5_addr;
+       
        creds = gensec_get_credentials(gensec_security);
        if (!creds) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -135,6 +140,44 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
                return NT_STATUS_INTERNAL_ERROR;
        }
 
+       my_addr = gensec_get_my_addr(gensec_security);
+       if (my_addr && my_addr->sockaddr) {
+               ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, 
+                                           my_addr->sockaddr, &my_krb5_addr);
+               if (ret) {
+                       DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", 
+                                smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, 
+                                                           ret, gensec_krb5_state)));
+                       talloc_free(gensec_krb5_state);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+       }
+
+       peer_addr = gensec_get_my_addr(gensec_security);
+       if (peer_addr && peer_addr->sockaddr) {
+               ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, 
+                                           peer_addr->sockaddr, &peer_krb5_addr);
+               if (ret) {
+                       DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", 
+                                smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, 
+                                                           ret, gensec_krb5_state)));
+                       talloc_free(gensec_krb5_state);
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+       }
+
+       ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context, 
+                                    gensec_krb5_state->auth_context,
+                                    my_addr ? &my_krb5_addr : NULL, 
+                                    peer_addr ? &peer_krb5_addr : NULL);
+       if (ret) {
+               DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n", 
+                        smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, 
+                                                   ret, gensec_krb5_state)));
+               talloc_free(gensec_krb5_state);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
        return NT_STATUS_OK;
 }
 
@@ -175,7 +218,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
        const char *hostname;
        krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED;
 
-       char *principal;
+       const char *principal;
        krb5_data in_data;
 
        hostname = gensec_get_target_hostname(gensec_security);
@@ -240,6 +283,10 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
                DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n", 
                          hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
                return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
+       case KRB5_KDC_UNREACH:
+               DEBUG(3, ("Cannot reach a KDC we require to contact host [%s]: %s\n",
+                         hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
+               return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
        case KRB5KDC_ERR_PREAUTH_FAILED:
        case KRB5KRB_AP_ERR_TKT_EXPIRED:
        case KRB5_CC_END:
@@ -423,11 +470,12 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
                }
                return nt_status;
        }
+
        case GENSEC_KRB5_DONE:
-               return NT_STATUS_OK;
+       default:
+               /* Asking too many times... */
+               return NT_STATUS_INVALID_PARAMETER;
        }
-       
-       return NT_STATUS_INVALID_PARAMETER;
 }
 
 static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security, 
@@ -501,6 +549,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
        } else {
                pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length);
                if (!pac.data) {
+                       talloc_free(mem_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
 
@@ -509,6 +558,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
                        DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", 
                                  smb_get_krb5_error_message(context, 
                                                             ret, mem_ctx)));
+                       talloc_free(mem_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
                
@@ -517,18 +567,17 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
                                                    gensec_krb5_state->smb_krb5_context->krb5_context,
                                                    NULL, gensec_krb5_state->keyblock,
                                                    client_principal,
-                                                   gensec_krb5_state->ticket->ticket.authtime);
+                                                   gensec_krb5_state->ticket->ticket.authtime, NULL);
                krb5_free_principal(context, client_principal);
 
                if (NT_STATUS_IS_OK(nt_status)) {
                        union netr_Validation validation;
                        validation.sam3 = &logon_info->info3;
-                       nt_status = make_server_info_netlogon_validation(gensec_krb5_state
+                       nt_status = make_server_info_netlogon_validation(mem_ctx
                                                                         NULL,
                                                                         3, &validation,
                                                                         &server_info); 
                }
-               talloc_free(mem_ctx);
        }
 
                
@@ -545,6 +594,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
                        DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", 
                                  smb_get_krb5_error_message(context, 
                                                             ret, mem_ctx)));
+                       talloc_free(mem_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
                
@@ -552,6 +602,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
                                        client_principal, &principal_string);
                krb5_free_principal(context, client_principal);
                if (ret) {
+                       talloc_free(mem_ctx);
                        return NT_STATUS_NO_MEMORY;
                }
 
@@ -566,16 +617,24 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
        }
 
        /* references the server_info into the session_info */
-       nt_status = auth_generate_session_info(gensec_krb5_state, server_info, &session_info);
-       talloc_free(mem_ctx);
+       nt_status = auth_generate_session_info(mem_ctx, server_info, &session_info);
 
-       NT_STATUS_NOT_OK_RETURN(nt_status);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               talloc_free(mem_ctx);
+               return nt_status;
+       }
 
        nt_status = gensec_krb5_session_key(gensec_security, &session_info->session_key);
-       NT_STATUS_NOT_OK_RETURN(nt_status);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               talloc_free(mem_ctx);
+               return nt_status;
+       }
 
        *_session_info = session_info;
 
+       talloc_steal(gensec_krb5_state, session_info);
+       talloc_free(mem_ctx);
        return NT_STATUS_OK;
 }
 
@@ -663,6 +722,7 @@ static const char *gensec_krb5_oids[] = {
 
 static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
        .name           = "fake_gssapi_krb5",
+       .sasl_name      = "GSSAPI",
        .auth_type      = DCERPC_AUTH_TYPE_KRB5,
        .oid            = gensec_krb5_oids,
        .client_start   = gensec_fake_gssapi_krb5_client_start,
@@ -672,7 +732,8 @@ static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
        .session_key    = gensec_krb5_session_key,
        .session_info   = gensec_krb5_session_info,
        .have_feature   = gensec_krb5_have_feature,
-       .enabled        = False
+       .enabled        = False,
+       .kerberos       = True
 };
 
 static const struct gensec_security_ops gensec_krb5_security_ops = {
@@ -685,7 +746,8 @@ static const struct gensec_security_ops gensec_krb5_security_ops = {
        .have_feature   = gensec_krb5_have_feature,
        .wrap           = gensec_krb5_wrap,
        .unwrap         = gensec_krb5_unwrap,
-       .enabled        = True
+       .enabled        = True,
+       .kerberos       = True
 };
 
 NTSTATUS gensec_krb5_init(void)