s4:kdc/wdc-samba4.c - fix user logins on specific workstations
[obnox/samba/samba-obnox.git] / source4 / kdc / wdc-samba4.c
index 805772f47fd4154c348a380de8e51a8e17876f30..2f4945c312ce98dd6c22162748ceff080afd2d04 100644 (file)
@@ -46,7 +46,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
                return EINVAL;
        }
 
-       ret = samba_make_krb5_pac(context, pac_blob, pac);
+       ret = samba_make_krb5_pac(context, pac_blob, NULL, pac);
 
        talloc_free(mem_ctx);
        return ret;
@@ -56,6 +56,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
 
 static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
                                           const krb5_principal client_principal,
+                                          const krb5_principal delegated_proxy_principal,
                                           struct hdb_entry_ex *client,
                                           struct hdb_entry_ex *server,
                                           struct hdb_entry_ex *krbtgt,
@@ -64,8 +65,12 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
        struct samba_kdc_entry *p = talloc_get_type(server->ctx, struct samba_kdc_entry);
        TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context");
        DATA_BLOB *pac_blob;
+       DATA_BLOB *deleg_blob = NULL;
        krb5_error_code ret;
        NTSTATUS nt_status;
+       struct PAC_SIGNATURE_DATA *pac_srv_sig;
+       struct PAC_SIGNATURE_DATA *pac_kdc_sig;
+       bool is_in_db, is_untrusted;
 
        if (!mem_ctx) {
                return ENOMEM;
@@ -80,7 +85,13 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
        /* If the krbtgt was generated by an RODC, and we are not that
         * RODC, then we need to regenerate the PAC - we can't trust
         * it */
-       if (samba_krbtgt_was_untrusted_rodc(krbtgt)) {
+       ret = samba_krbtgt_is_in_db(krbtgt, &is_in_db, &is_untrusted);
+       if (ret != 0) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       if (is_untrusted) {
                if (client == NULL) {
                        return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
                }
@@ -96,19 +107,63 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
                        return ENOMEM;
                }
 
+               pac_srv_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA);
+               if (!pac_srv_sig) {
+                       talloc_free(mem_ctx);
+                       return ENOMEM;
+               }
+
+               pac_kdc_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA);
+               if (!pac_kdc_sig) {
+                       talloc_free(mem_ctx);
+                       return ENOMEM;
+               }
+
                nt_status = samba_kdc_update_pac_blob(mem_ctx, context,
-                                                     pac, pac_blob);
+                                                     *pac, pac_blob,
+                                                     pac_srv_sig, pac_kdc_sig);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(0, ("Building PAC failed: %s\n",
                                  nt_errstr(nt_status)));
                        talloc_free(mem_ctx);
                        return EINVAL;
                }
+               
+               if (is_in_db) {
+                       /* Now check the KDC signature, fetching the correct key based on the enc type */
+                       ret = kdc_check_pac(context, pac_srv_sig->signature, pac_kdc_sig, krbtgt);
+                       if (ret != 0) {
+                               DEBUG(1, ("PAC KDC signature failed to verify\n"));
+                               talloc_free(mem_ctx);
+                               return ret;
+                       }
+               }
        }
+
+       if (delegated_proxy_principal) {
+               deleg_blob = talloc_zero(mem_ctx, DATA_BLOB);
+               if (!deleg_blob) {
+                       talloc_free(mem_ctx);
+                       return ENOMEM;
+               }
+
+               nt_status = samba_kdc_update_delegation_info_blob(mem_ctx,
+                                       context, *pac,
+                                       server->entry.principal,
+                                       delegated_proxy_principal,
+                                       deleg_blob);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       DEBUG(0, ("Building PAC failed: %s\n",
+                                 nt_errstr(nt_status)));
+                       talloc_free(mem_ctx);
+                       return EINVAL;
+               }
+       }
+
        /* We now completely regenerate this pac */
        krb5_pac_free(context, *pac);
 
-       ret = samba_make_krb5_pac(context, pac_blob, pac);
+       ret = samba_make_krb5_pac(context, pac_blob, deleg_blob, pac);
 
        talloc_free(mem_ctx);
        return ret;
@@ -132,14 +187,15 @@ static char *get_netbios_name(TALLOC_CTX *mem_ctx, HostAddresses *addrs)
                }
        }
 
-       if (nb_name == NULL) {
+       if ((nb_name == NULL) || (nb_name[0] == '\0')) {
                return NULL;
        }
 
        /* Strip space padding */
-       i = strlen(nb_name) - 1;
-       while (i > 0 && nb_name[i] == ' ') {
-               nb_name[i] = '\0';
+       for (len = strlen(nb_name) - 1;
+            (len > 0) && (nb_name[len] == ' ');
+            --len) {
+               nb_name[len] = '\0';
        }
 
        return nb_name;
@@ -212,7 +268,7 @@ static void samba_wdc_plugin_fini(void *ptr)
 }
 
 struct krb5plugin_windc_ftable windc_plugin_table = {
-       .minor_version = KRB5_WINDC_PLUGING_MINOR,
+       .minor_version = KRB5_WINDC_PLUGIN_MINOR,
        .init = samba_wdc_plugin_init,
        .fini = samba_wdc_plugin_fini,
        .pac_generate = samba_wdc_get_pac,