- /* I can not find documentation of any other purpose for the
- * DirectoryNames field.
- */
- /*
- * Try to synthesize a principal:
- * service '/' fqdn '@' realm
- */
- if (options->k5service && options->k5realm && options->fqdn) {
- /* should k5princ be utf8 encoded? */
- size_t len;
- char *p = strchr( options->fqdn, ':' );
- if (p)
- *p = '\0';
- len = strlen( options->k5service )
- + strlen( options->fqdn )
- + strlen( options->k5realm );
- len+=2; /* '/' and '@' */
- if ( len > 255 || len+2 > maxstatuslen - offset) {
- *data++ = 0;
- LOG ( log_error, logtype_afpd, "status: could not set directory service list, no more room");
- }
- else {
- *data++ = 1; /* DirectoryNamesCount */
- *data++ = len;
- snprintf( data, len + 1, "%s/%s@%s", options->k5service,
- options->fqdn, options->k5realm );
- data += len;
- if (p)
- *p = ':';
- }
+ char *DirectoryNamesCount = data++;
+ char *DirectoryNames = data;
+ size_t size = sizeof(uint8_t);
+ *DirectoryNamesCount = 0;
+
+ if (!uam_gss_enabled())
+ goto offset_calc;
+
+#ifdef HAVE_KERBEROS
+ krb5_context context;
+ krb5_error_code ret;
+ const char *error_msg;
+
+ if (krb5_init_context(&context)) {
+ LOG(log_error, logtype_afpd,
+ "status:DirectoryNames failed to intialize a krb5_context");
+ goto offset_calc;
+ }
+
+ krb5_keytab keytab;
+ if ((ret = krb5_kt_default(context, &keytab)))
+ goto krb5_error;
+
+ // figure out which service principal to use
+ krb5_keytab_entry entry;
+ char *principal;
+ if (options->k5service && options->fqdn && options->k5realm) {
+ LOG(log_debug, logtype_afpd,
+ "status:DirectoryNames: using service principal specified in options");
+
+ krb5_principal service_principal;
+ if ((ret = krb5_build_principal(context,
+ &service_principal,
+ strlen(options->k5realm),
+ options->k5realm,
+ options->k5service,
+ options->fqdn,
+ NULL)))
+ goto krb5_error;
+
+ // try to get the given service principal from keytab
+ ret = krb5_kt_get_entry(context,
+ keytab,
+ service_principal,
+ 0, // kvno - wildcard
+ 0, // enctype - wildcard
+ &entry);
+ if (ret == KRB5_KT_NOTFOUND) {
+ krb5_unparse_name(context, service_principal, &principal);
+ LOG(log_error, logtype_afpd,
+ "status:DirectoryNames: specified service principal '%s' not found in keytab",
+ principal);
+ // XXX: should this be krb5_xfree?
+#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
+ krb5_free_unparsed_name(context, principal);
+#else
+ krb5_xfree(principal);
+#endif
+ goto krb5_cleanup;
+ }
+ krb5_free_principal(context, service_principal);
+ if (ret)
+ goto krb5_error;