Beispiel #1
0
int
heim_digest_verify(heim_digest_t context, char **response)
{
    CC_MD5_CTX ctx;
    char *a1, *a2;
    uint8_t md[CC_MD5_DIGEST_LENGTH];
    char *str;
    int res;

    if (response)
	*response = NULL;

    if (context->serverMethod == NULL) {
	if (context->type != HEIM_DIGEST_TYPE_RFC2069)
	    context->serverMethod = strdup("AUTHENTICATE");
	else
	    context->serverMethod = strdup("GET");
    }

    a1 = build_A1_hash(context->type,
		       context->clientUsername, context->password,
		       context->serverRealm, context->serverNonce,
		       context->clientNonce, context->auth_id);
    if (a1 == NULL)
      return ENOMEM;

    str = build_digest(context, a1, context->serverMethod);
    if (str == NULL) {
	MEMSET_FREE_AND_CLEAR(a1);
	return ENOMEM;
    }

    res = (strcmp(str, context->clientResponse) == 0) ? 0 : EINVAL;
    free(str);
    if (res) {
	MEMSET_FREE_AND_CLEAR(a1);
	return res;
    }

    /* build server_response */
    if (response) {
	str = build_digest(context, a1, NULL);
	if (str == NULL) {
	    MEMSET_FREE_AND_CLEAR(a1);
	    return ENOMEM;
	}

	asprintf(response, "rspauth=%s", str);
	free(str);
    }
    MEMSET_FREE_AND_CLEAR(a1);

    return 0;
}
const char *
heim_digest_server_response(heim_digest_t context)
{
    char *a1;
    
    if (context->serverNonce == NULL)
	return NULL;
    if (context->clientURI == NULL)
	return NULL;

    a1 = build_A1_hash(context);
    if (a1 == NULL)
	return NULL;
    
    build_server_response(context, a1, NULL);
    MEMSET_FREE_AND_CLEAR(a1);
    
    return context->serverReply;
}
int
heim_digest_verify(heim_digest_t context, char **response)
{
    char *a1;
    char *str;
    int res;

    if (response)
	*response = NULL;
    
    set_auth_method(context);

    a1 = build_A1_hash(context);
    if (a1 == NULL)
      return ENOMEM;

    str = build_digest(context, a1, context->serverMethod);
    if (str == NULL) {
	MEMSET_FREE_AND_CLEAR(a1);
	return ENOMEM;
    }

    res = (strcmp(str, context->clientResponse) == 0) ? 0 : EINVAL;
    free(str);
    if (res) {
	MEMSET_FREE_AND_CLEAR(a1);
	return res;
    }

    /* build server_response */
    build_server_response(context, a1, response);
    MEMSET_FREE_AND_CLEAR(a1);
    /* XXX break ABI and return internally allocated string instead */
    if (response)
	*response = strdup(*response);

    return 0;
}
const char *
heim_digest_create_response(heim_digest_t context, char **response)
{
    char *a1, *str, *cnonce = NULL, *opaque = NULL, *uri = NULL, *nc = NULL;
    
    if (response)
	*response = NULL;
    
    if (context->clientUsername == NULL || context->clientURI == NULL)
	return NULL;
    
    if (context->clientRealm == NULL) {
	if (context->serverRealm == NULL)
	    return NULL;
	if ((context->clientRealm = strdup(context->serverRealm)) == NULL)
	    return NULL;
    }
    
    if (context->type != HEIM_DIGEST_TYPE_RFC2069) {
	if (context->clientNC == NULL) {
	    if ((context->clientNC = strdup("00000001")) == NULL)
		return NULL;
	}
	if (context->clientNonce == NULL) {
	    if ((context->clientNonce = generate_nonce()) == NULL)
		return NULL;
	}

	/**
	 * If using non RFC2069, appropriate QOP should be set.
	 *
	 * Pick QOP from server if not given, if its a list, pick the first entry
	 */
	if (context->clientQOP == NULL) {
	    char *r;
	    if (context->serverQOP == NULL)
		return NULL;
	    r = strchr(context->serverQOP, ',');
	    if (r == NULL) {
		if ((context->clientQOP = strdup(context->serverQOP)) == NULL)
			return NULL;
	    } else {
		size_t len = (r - context->serverQOP) + 1;
		if ((context->clientQOP = malloc(len)) == NULL)
		    return NULL;
		strlcpy(context->clientQOP, context->serverQOP, len);
	    }
	}
    }
	    
    set_auth_method(context);
    
    a1 = build_A1_hash(context);
    if (a1 == NULL)
	return NULL;
    
    str = build_digest(context, a1, context->serverMethod);
    if (str == NULL) {
	MEMSET_FREE_AND_CLEAR(a1);
	return NULL;
    }
    
    MEMSET_FREE_AND_CLEAR(context->clientResponse);
    context->clientResponse = str;
    
    if (context->clientURI) {
	const char *name = "digest-uri";
	if (context->type != HEIM_DIGEST_TYPE_RFC2831)
	    name = "uri";
	asprintf(&uri, ",%s=\"%s\"", name, context->clientURI);
    }
    
    if (context->serverOpaque)
	asprintf(&opaque, ",opaque=\"%s\"", context->serverOpaque);
    
    if (context->clientNonce)
	asprintf(&cnonce, ",cnonce=\"%s\"", context->clientNonce);

    if (context->clientNC)
	asprintf(&nc, ",nc=%s", context->clientNC);
    
    asprintf(&context->clientReply,
	     "username=%s,realm=%s,nonce=\"%s\",qop=\"%s\"%s%s%s,response=\"%s\"%s",
	     context->clientUsername, context->clientRealm,
	     context->serverNonce,
	     context->clientQOP,
	     uri ? uri : "",
	     cnonce ? cnonce : "",
	     nc ? nc : "",
	     context->clientResponse,
	     opaque ? opaque : "");
    
    build_server_response(context, a1, response);
    MEMSET_FREE_AND_CLEAR(a1);
    FREE_AND_CLEAR(uri);
    FREE_AND_CLEAR(opaque);
    FREE_AND_CLEAR(cnonce);
    FREE_AND_CLEAR(nc);
    
    return context->clientReply;
}