lib/krb5_wrap: use krb5_const_principal in smb_krb5_create_key_from_string.
[kai/samba-autobuild/.git] / source3 / libads / kerberos.c
index 80f99de4823ec39dfd54f9ba90a47bcf17431d7a..d5d8e2afc034f946589226466e584a87257a7789 100644 (file)
@@ -356,7 +356,7 @@ char* kerberos_standard_des_salt( void )
        fstring salt;
 
        fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() );
-       strlower_m( salt );
+       (void)strlower_m( salt );
        fstrcat( salt, lp_realm() );
 
        return SMB_STRDUP( salt );
@@ -490,7 +490,12 @@ int create_kerberos_key_from_string(krb5_context context,
                return 0;
        }
        salt_princ = kerberos_fetch_salt_princ_for_host_princ(context, host_princ, enctype);
-       ret = create_kerberos_key_from_string_direct(context, salt_princ ? salt_princ : host_princ, password, key, enctype);
+       ret = smb_krb5_create_key_from_string(context,
+                                             salt_princ ? salt_princ : host_princ,
+                                             NULL,
+                                             password,
+                                             enctype,
+                                             key);
        if (salt_princ) {
                krb5_free_principal(context, salt_princ);
        }
@@ -592,70 +597,6 @@ int kerberos_kinit_password(const char *principal,
 /************************************************************************
 ************************************************************************/
 
-static char *print_kdc_line(char *mem_ctx,
-                       const char *prev_line,
-                       const struct sockaddr_storage *pss,
-                       const char *kdc_name)
-{
-       char addr[INET6_ADDRSTRLEN];
-       uint16_t port = get_sockaddr_port(pss);
-
-       if (pss->ss_family == AF_INET) {
-               return talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
-                                      prev_line,
-                                      print_canonical_sockaddr(mem_ctx, pss));
-       }
-
-       /*
-        * IPv6 starts here
-        */
-
-       DEBUG(10, ("print_kdc_line: IPv6 case for kdc_name: %s, port: %d\n",
-                  kdc_name, port));
-
-       if (port != 0 && port != DEFAULT_KRB5_PORT) {
-               /* Currently for IPv6 we can't specify a non-default
-                  krb5 port with an address, as this requires a ':'.
-                  Resolve to a name. */
-               char hostname[MAX_DNS_NAME_LENGTH];
-               int ret = sys_getnameinfo((const struct sockaddr *)pss,
-                                         sizeof(*pss),
-                                         hostname, sizeof(hostname),
-                                         NULL, 0,
-                                         NI_NAMEREQD);
-               if (ret) {
-                       DEBUG(0,("print_kdc_line: can't resolve name "
-                                "for kdc with non-default port %s. "
-                                "Error %s\n.",
-                                print_canonical_sockaddr(mem_ctx, pss),
-                                gai_strerror(ret)));
-                       return NULL;
-               }
-               /* Success, use host:port */
-               return talloc_asprintf(mem_ctx,
-                                      "%s\tkdc = %s:%u\n",
-                                      prev_line,
-                                      hostname,
-                                      (unsigned int)port);
-       }
-
-       /* no krb5 lib currently supports "kdc = ipv6 address"
-        * at all, so just fill in just the kdc_name if we have
-        * it and let the krb5 lib figure out the appropriate
-        * ipv6 address - gd */
-
-       if (kdc_name) {
-               return talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
-                                      prev_line, kdc_name);
-       }
-
-       return talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
-                              prev_line,
-                              print_sockaddr(addr,
-                                             sizeof(addr),
-                                             pss));
-}
-
 /************************************************************************
  Create a string list of available kdc's, possibly searching by sitename.
  Does DNS queries.
@@ -679,11 +620,35 @@ static void add_sockaddr_unique(struct sockaddr_storage *addrs, int *num_addrs,
        *num_addrs += 1;
 }
 
+/* print_canonical_sockaddr prints an ipv6 addr in the form of
+* [ipv6.addr]. This string, when put in a generated krb5.conf file is not
+* always properly dealt with by some older krb5 libraries. Adding the hard-coded
+* portnumber workarounds the issue. - gd */
+
+static char *print_canonical_sockaddr_with_port(TALLOC_CTX *mem_ctx,
+                                               const struct sockaddr_storage *pss)
+{
+       char *str = NULL;
+
+       str = print_canonical_sockaddr(mem_ctx, pss);
+       if (str == NULL) {
+               return NULL;
+       }
+
+       if (pss->ss_family != AF_INET6) {
+               return str;
+       }
+
+#if defined(HAVE_IPV6)
+       str = talloc_asprintf_append(str, ":88");
+#endif
+       return str;
+}
+
 static char *get_kdc_ip_string(char *mem_ctx,
                const char *realm,
                const char *sitename,
-               const struct sockaddr_storage *pss,
-               const char *kdc_name)
+               const struct sockaddr_storage *pss)
 {
        TALLOC_CTX *frame = talloc_stackframe();
        int i;
@@ -698,9 +663,11 @@ static char *get_kdc_ip_string(char *mem_ctx,
        char *result = NULL;
        struct netlogon_samlogon_response **responses = NULL;
        NTSTATUS status;
-       char *kdc_str = print_kdc_line(mem_ctx, "", pss, kdc_name);
+       char *kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", "",
+                                       print_canonical_sockaddr_with_port(mem_ctx, pss));
 
        if (kdc_str == NULL) {
+               TALLOC_FREE(frame);
                return NULL;
        }
 
@@ -787,9 +754,9 @@ static char *get_kdc_ip_string(char *mem_ctx,
                }
 
                /* Append to the string - inefficient but not done often. */
-               new_kdc_str = print_kdc_line(mem_ctx, kdc_str,
-                                            &dc_addrs[i],
-                                            kdc_name);
+               new_kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
+                                             kdc_str,
+                                             print_canonical_sockaddr_with_port(mem_ctx, &dc_addrs[i]));
                if (new_kdc_str == NULL) {
                        goto fail;
                }
@@ -818,8 +785,7 @@ fail:
 bool create_local_private_krb5_conf_for_domain(const char *realm,
                                                const char *domain,
                                                const char *sitename,
-                                               const struct sockaddr_storage *pss,
-                                               const char *kdc_name)
+                                               const struct sockaddr_storage *pss)
 {
        char *dname;
        char *tmpname = NULL;
@@ -831,11 +797,23 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
        int fd;
        char *realm_upper = NULL;
        bool result = false;
+       char *aes_enctypes = NULL;
+       mode_t mask;
 
        if (!lp_create_krb5_conf()) {
                return false;
        }
 
+       if (realm == NULL) {
+               DEBUG(0, ("No realm has been specified! Do you really want to "
+                         "join an Active Directory server?\n"));
+               return false;
+       }
+
+       if (domain == NULL || pss == NULL) {
+               return false;
+       }
+
        dname = lock_path("smb_krb5");
        if (!dname) {
                return false;
@@ -865,19 +843,38 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                goto done;
        }
 
-       kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss, kdc_name);
+       kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss);
        if (!kdc_ip_string) {
                goto done;
        }
 
+       aes_enctypes = talloc_strdup(fname, "");
+       if (aes_enctypes == NULL) {
+               goto done;
+       }
+
+#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
+       aes_enctypes = talloc_asprintf_append(aes_enctypes, "%s", "aes256-cts-hmac-sha1-96 ");
+       if (aes_enctypes == NULL) {
+               goto done;
+       }
+#endif
+#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+       aes_enctypes = talloc_asprintf_append(aes_enctypes, "%s", "aes128-cts-hmac-sha1-96");
+       if (aes_enctypes == NULL) {
+               goto done;
+       }
+#endif
+
        file_contents = talloc_asprintf(fname,
                                        "[libdefaults]\n\tdefault_realm = %s\n"
-                                       "\tdefault_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
-                                       "\tdefault_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
-                                       "\tpreferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n"
+                                       "\tdefault_tgs_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
+                                       "\tdefault_tkt_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
+                                       "\tpreferred_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n"
                                        "[realms]\n\t%s = {\n"
                                        "\t%s\t}\n",
-                                       realm_upper, realm_upper, kdc_ip_string);
+                                       realm_upper, aes_enctypes, aes_enctypes, aes_enctypes,
+                                       realm_upper, kdc_ip_string);
 
        if (!file_contents) {
                goto done;
@@ -885,7 +882,9 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
 
        flen = strlen(file_contents);
 
+       mask = umask(S_IRWXO | S_IRWXG);
        fd = mkstemp(tmpname);
+       umask(mask);
        if (fd == -1) {
                DEBUG(0,("create_local_private_krb5_conf_for_domain: smb_mkstemp failed,"
                        " for file %s. Errno %s\n",