return retval;
}
+/* Encryption types supported by the kernel rpcsec_gss code */
+int num_krb5_enctypes = 0;
+krb5_enctype *krb5_enctypes = NULL;
+
+/*
+ * Parse the supported encryption type information
+ */
+static int
+parse_enctypes(char *enctypes)
+{
+ int n = 0;
+ char *curr, *comma;
+ int i;
+ static char *cached_types;
+
+ if (cached_types && strcmp(cached_types, enctypes) == 0)
+ return 0;
+ free(cached_types);
+
+ if (krb5_enctypes != NULL) {
+ free(krb5_enctypes);
+ krb5_enctypes = NULL;
+ num_krb5_enctypes = 0;
+ }
+
+ /* count the number of commas */
+ for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
+ comma = strchr(curr, ',');
+ if (comma != NULL)
+ n++;
+ else
+ break;
+ }
+ /* If no more commas and we're not at the end, there's one more value */
+ if (*curr != '\0')
+ n++;
+
+ /* Empty string, return an error */
+ if (n == 0)
+ return ENOENT;
+
+ /* Allocate space for enctypes array */
+ if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
+ return ENOMEM;
+ }
+
+ /* Now parse each value into the array */
+ for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
+ krb5_enctypes[i++] = atoi(curr);
+ comma = strchr(curr, ',');
+ if (comma == NULL)
+ break;
+ }
+
+ num_krb5_enctypes = n;
+ if (cached_types = malloc(strlen(enctypes)+1))
+ strcpy(cached_types, enctypes);
+
+ return 0;
+}
+
static int
do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
gss_buffer_desc *context_token)
{
uid_t uid;
char *lbuf = NULL;
- int lbuflen = 0;
+ int lbuflen = 0, code;
char *p;
char *mech = NULL;
char *target = NULL;
char *service = NULL;
+ char *enctypes = NULL;
printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
goto out;
}
+ /* read supported encryption types if supplied */
+ if ((p = strstr(lbuf, "enctypes=")) != NULL) {
+ enctypes = malloc(lbuflen);
+ if (!enctypes)
+ goto out;
+ if (sscanf(p, "enctypes=%s", enctypes) != 1) {
+ printerr(0, "WARNING: handle_gssd_upcall: "
+ "failed to parse target name "
+ "in upcall string '%s'\n", lbuf);
+ goto out;
+ }
+ if (parse_enctypes(enctypes) != 0) {
+ printerr(0, "WARNING: handle_gssd_upcall: "
+ "parsing encryption types failed: errno %d\n", code);
+ }
+ }
+
/* read target name */
if ((p = strstr(lbuf, "target=")) != NULL) {
target = malloc(lbuflen);
out:
free(lbuf);
free(mech);
+ free(enctypes);
free(target);
free(service);
return;
ENCTYPE_DES_CBC_MD5,
ENCTYPE_DES_CBC_MD4 };
int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
+ extern int num_krb5_enctypes;
+ extern krb5_enctype *krb5_enctypes;
/* We only care about getting a krb5 cred */
desired_mechs.count = 1;
return -1;
}
- maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
- num_enctypes, &enctypes);
+ /*
+ * If we failed for any reason to produce global
+ * list of supported enctypes, use local default here.
+ */
+ if (krb5_enctypes == NULL)
+ maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
+ &krb5oid, num_enctypes, enctypes);
+ else
+ maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
+ &krb5oid, num_krb5_enctypes, krb5_enctypes);
+
if (maj_stat != GSS_S_COMPLETE) {
pgsserr("gss_set_allowable_enctypes",
maj_stat, min_stat, &krb5oid);