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; }
static void clear_context(heim_digest_t context) { MEMSET_FREE_AND_CLEAR(context->password); memset(context->SecretHash, 0, sizeof(context->SecretHash)); context->flags &= ~(F_HAVE_HASH); FREE_AND_CLEAR(context->serverNonce); FREE_AND_CLEAR(context->serverRealm); FREE_AND_CLEAR(context->serverQOP); FREE_AND_CLEAR(context->serverMethod); FREE_AND_CLEAR(context->serverMaxbuf); FREE_AND_CLEAR(context->serverOpaque); FREE_AND_CLEAR(context->clientUsername); FREE_AND_CLEAR(context->clientResponse); FREE_AND_CLEAR(context->clientURI); FREE_AND_CLEAR(context->clientRealm); FREE_AND_CLEAR(context->clientNonce); FREE_AND_CLEAR(context->clientQOP); FREE_AND_CLEAR(context->clientNC); FREE_AND_CLEAR(context->serverAlgorithm); FREE_AND_CLEAR(context->auth_id); FREE_AND_CLEAR(context->serverChallenge); FREE_AND_CLEAR(context->clientReply); FREE_AND_CLEAR(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_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; }
static void build_server_response(heim_digest_t context, char *a1, char **response) { char *str; str = build_digest(context, a1, NULL); if (str == NULL) { MEMSET_FREE_AND_CLEAR(a1); return; } FREE_AND_CLEAR(context->serverReply); asprintf(&context->serverReply, "%srspauth=%s", (context->flags & F_USE_PREFIX) ? digest_prefix : "", str); free(str); if (response) *response = context->serverReply; }
static void clear_context(heim_digest_t context) { MEMSET_FREE_AND_CLEAR(context->password); memset(context->SecretHash, 0, sizeof(context->SecretHash)); FREE_AND_CLEAR(context->serverNonce); FREE_AND_CLEAR(context->serverRealm); FREE_AND_CLEAR(context->serverQOP); FREE_AND_CLEAR(context->serverMethod); FREE_AND_CLEAR(context->clientUsername); FREE_AND_CLEAR(context->clientResponse); FREE_AND_CLEAR(context->clientURI); FREE_AND_CLEAR(context->clientRealm); FREE_AND_CLEAR(context->clientNonce); FREE_AND_CLEAR(context->clientQOP); FREE_AND_CLEAR(context->clientNC); FREE_AND_CLEAR(context->serverAlgorithm); FREE_AND_CLEAR(context->auth_id); }
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; }