Exemplo n.º 1
0
/*  Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host),
**  because I dont't know how to stub varargs.
**  Returns krb5_error_code == ENOMEM on alloc error, otherwise
**  passes back newly constructed principal, which should be freed by caller.
*/
krb5_error_code
kssl_build_principal_2(
	/* UPDATE */	krb5_context	context,
	/* OUT    */	krb5_principal	*princ,
	/* IN     */	int rlen,  const char *realm,
	/* IN	  */	int slen,  const char *svc,
	/* IN	  */	int hlen,  const char *host)
{
	krb5_data		*p_data = NULL;
	krb5_principal		new_p = NULL;
        char			*new_r = NULL;

	if ((p_data = (krb5_data *)calloc(2, sizeof(krb5_data))) == NULL ||
	    (new_p = (krb5_principal)calloc(1, sizeof(krb5_principal_data)))
	    == NULL)
		goto err;
	new_p->length = 2;
	new_p->data = p_data;

	if ((new_r = calloc(1, rlen + 1)) == NULL)
		goto err;
	memcpy(new_r, realm, rlen);
	krb5_princ_set_realm_length(context, new_p, rlen);
	krb5_princ_set_realm_data(context, new_p, new_r);

	if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL)
		goto err;
	memcpy(new_p->data[0].data, svc, slen);
	new_p->data[0].length = slen;

	if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL)
		goto err;
	memcpy(new_p->data[1].data, host, hlen);
	new_p->data[1].length = hlen;
	
	krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN;
	*princ = new_p;
	return 0;

err:
	if (new_p && new_p[0].data)
		free(new_p[0].data);
	if (new_p && new_p[1].data)
		free(new_p[1].data);
	if (new_p)
		free(new_p);
	if (new_r)
		free(new_r);
	return ENOMEM;
}
Exemplo n.º 2
0
/*
 * May the fleas of a thousand camels infest the ISO, they who think
 * that arbitrarily large multi-component names are a Good Thing.....
 */
static krb5_error_code
k5_parse_name(krb5_context context, const char *name,
	      int flags, krb5_principal *nprincipal)
{
	register const char	*cp;
	register char	*q;
	register int	i,c,size;
	int		components = 0;
	const char	*parsed_realm = NULL;
	int		fcompsize[FCOMPNUM];
	unsigned int	realmsize = 0;
	char		*default_realm = NULL;
	int		default_realm_size = 0;
	char		*tmpdata;
	krb5_principal	principal;
	krb5_error_code retval;
	unsigned int	enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE);
	int		first_at;

	/*
	 * Pass 1.  Find out how many components there are to the name,
	 * and get string sizes for the first FCOMPNUM components. For
	 * enterprise principal names (UPNs), there is only a single
	 * component.
	 */
	size = 0;
	for (i=0,cp = name, first_at = 1; (c = *cp); cp++) {
		if (c == QUOTECHAR) {
			cp++;
			if (!(c = *cp))
				/*
			 	 * QUOTECHAR can't be at the last
			 	 * character of the name!
			 	 */
				return(KRB5_PARSE_MALFORMED);
			size++;
			continue;
		} else if (c == COMPONENT_SEP && !enterprise) {
			if (parsed_realm)
				/*
				 * Shouldn't see a component separator
				 * after we've parsed out the realm name!
				 */
				return(KRB5_PARSE_MALFORMED);
			if (i < FCOMPNUM) {
				fcompsize[i] = size;
			}
			size = 0;
			i++;
		} else if (c == REALM_SEP && (!enterprise || !first_at)) {
			if (parsed_realm)
				/*
				 * Multiple realm separaters
				 * not allowed; zero-length realms are.
				 */
				return(KRB5_PARSE_MALFORMED);
			parsed_realm = cp + 1;
			if (i < FCOMPNUM) {
				fcompsize[i] = size;
			}
			size = 0;
		} else {
			if (c == REALM_SEP && enterprise && first_at)
				first_at = 0;

			size++;
		}
	}
	if (parsed_realm != NULL)
		realmsize = size;
	else if (i < FCOMPNUM) 
		fcompsize[i] = size;
	components = i + 1;
	/*
	 * Now, we allocate the principal structure and all of its
	 * component pieces
	 */
	principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
	if (principal == NULL) {
	    return(ENOMEM);
	}
	principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components);
	if (principal->data == NULL) {
	    krb5_xfree((char *)principal);
	    return ENOMEM;
	}
	principal->length = components;

	/*
	 * If a realm was not found, then use the default realm, unless
	 * KRB5_PRINCIPAL_PARSE_NO_REALM was specified in which case the
	 * realm will be empty.
	 */
	if (!parsed_realm) {
	    if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
		krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
				       "Principal %s is missing required realm", name);
		krb5_xfree(principal->data);
		krb5_xfree(principal);
		return KRB5_PARSE_MALFORMED;
	    }
	    if (!default_realm && (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) == 0) {
		retval = krb5_get_default_realm(context, &default_realm);
		if (retval) {
		    krb5_xfree(principal->data);
		    krb5_xfree((char *)principal);
		    return(retval);
		}
		default_realm_size = strlen(default_realm);
	    }
	    realmsize = default_realm_size;
	} else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
	    krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
				  "Principal %s has realm present", name);
	    krb5_xfree(principal->data);
	    krb5_xfree(principal);
	    return KRB5_PARSE_MALFORMED;
	}

	/*
	 * Pass 2.  Happens only if there were more than FCOMPNUM
	 * component; if this happens, someone should be shot
	 * immediately.  Nevertheless, we will attempt to handle said
	 * case..... <martyred sigh>
	 */
	if (components >= FCOMPNUM) {
		size = 0;
		parsed_realm = NULL;
		for (i=0,cp = name; (c = *cp); cp++) {
			if (c == QUOTECHAR) {
				cp++;
				size++;
			} else if (c == COMPONENT_SEP) {
				if (krb5_princ_size(context, principal) > i)
					krb5_princ_component(context, principal, i)->length = size;
				size = 0;
				i++;
			} else if (c == REALM_SEP) {
				if (krb5_princ_size(context, principal) > i)
					krb5_princ_component(context, principal, i)->length = size;
				size = 0;
				parsed_realm = cp+1;
			} else
				size++;
		}
		if (parsed_realm)
			krb5_princ_realm(context, principal)->length = size;
		else
			if (krb5_princ_size(context, principal) > i)
				krb5_princ_component(context, principal, i)->length = size;
		if (i + 1 != components) {
#if !defined(_WIN32)
		    fprintf(stderr,
			    "Programming error in krb5_parse_name!");
#endif
		    assert(i + 1 == components);
		    abort();
		}
	} else {
		/*
		 * If there were fewer than FCOMPSIZE components (the
		 * usual case), then just copy the sizes to the
		 * principal structure
		 */
		for (i=0; i < components; i++)
			krb5_princ_component(context, principal, i)->length = fcompsize[i];
	}
	/*	
	 * Now, we need to allocate the space for the strings themselves.....
	 */
	tmpdata = malloc(realmsize + 1);
	if (tmpdata == 0) {
		krb5_xfree(principal->data);
		krb5_xfree(principal);
		krb5_xfree(default_realm);
		return ENOMEM;
	}
	krb5_princ_set_realm_length(context, principal, realmsize);
	krb5_princ_set_realm_data(context, principal, tmpdata);
	for (i=0; i < components; i++) {
		char *tmpdata2 =
		  malloc(krb5_princ_component(context, principal, i)->length + 1);
		if (tmpdata2 == NULL) {
			for (i--; i >= 0; i--)
				krb5_xfree(krb5_princ_component(context, principal, i)->data);
			krb5_xfree(krb5_princ_realm(context, principal)->data);
			krb5_xfree(principal->data);
			krb5_xfree(principal);
			krb5_xfree(default_realm);
			return(ENOMEM);
		}
		krb5_princ_component(context, principal, i)->data = tmpdata2;
		krb5_princ_component(context, principal, i)->magic = KV5M_DATA;
	}
	
	/*
	 * Pass 3.  Now we go through the string a *third* time, this
	 * time filling in the krb5_principal structure which we just
	 * allocated.
	 */
	q = krb5_princ_component(context, principal, 0)->data;
	for (i=0,cp = name, first_at = 1; (c = *cp); cp++) {
		if (c == QUOTECHAR) {
			cp++;
			switch (c = *cp) {
			case 'n':
				*q++ = '\n';
				break;
			case 't':
				*q++ = '\t';
				break;
			case 'b':
				*q++ = '\b';
				break;
			case '0':
				*q++ = '\0';
				break;
			default:
				*q++ = c;
				break;
			}
		} else if (c == COMPONENT_SEP && !enterprise) {
			i++;
			*q++ = '\0';
			q = krb5_princ_component(context, principal, i)->data;
		} else if (c == REALM_SEP && (!enterprise || !first_at)) {
			i++;
			*q++ = '\0';
			q = krb5_princ_realm(context, principal)->data;
		} else {
			if (c == REALM_SEP && enterprise && first_at)
				first_at = 0;

			*q++ = c;
		}
	}
	*q++ = '\0';
	if (!parsed_realm) {
		if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM)
			(krb5_princ_realm(context, principal)->data)[0] = '\0';
		else
			strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize+1);
	}
	/*
	 * Alright, we're done.  Now stuff a pointer to this monstrosity
	 * into the return variable, and let's get out of here.
	 */
	if (enterprise)
		krb5_princ_type(context, principal) = KRB5_NT_ENTERPRISE_PRINCIPAL;
	else
		krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL;
	principal->magic = KV5M_PRINCIPAL;
	principal->realm.magic = KV5M_DATA;
	*nprincipal = principal;

	if (default_realm != NULL)
		krb5_xfree(default_realm);

	return(0);
}