void iks_md5(const char *data, char *buf) { iksmd5 *md5 = iks_md5_new(); iks_md5_hash(md5, (const unsigned char*)data, strlen(data), 1); iks_md5_print(md5, buf); iks_md5_delete(md5); }
static iks *make_sasl_response(struct stream_data *data, char *message) { iks *x = NULL; char *realm, *realm_end; char *nonce, *nonce_end; char cnonce[CNONCE_LEN * 8 + 1]; iksmd5 *md5; unsigned char a1_h[16], a1[33], a2[33], response_value[33]; char *response, *response_coded; int i; parse_digest(message, "realm=\"", &realm, &realm_end); parse_digest(message, "nonce=\"", &nonce, &nonce_end); /* nonce is necessary for auth */ if(!nonce || !nonce_end) return NULL; *nonce_end = '\0'; /* if no realm is given use the server hostname */ if(realm) { if(!realm_end) return NULL; *realm_end = '\0'; } else { realm = (char *) data->server; } /* generate random client challenge */ for(i = 0; i < CNONCE_LEN; ++i) sprintf(cnonce + i * 8, "%08x", rand()); md5 = iks_md5_new(); if(!md5) return NULL; iks_md5_hash(md5, (const unsigned char*)data->auth_username, iks_strlen(data->auth_username), 0); iks_md5_hash(md5, (const unsigned char*)":", 1, 0); iks_md5_hash(md5, (const unsigned char*)realm, iks_strlen(realm), 0); iks_md5_hash(md5, (const unsigned char*)":", 1, 0); iks_md5_hash(md5, (const unsigned char*)data->auth_pass, iks_strlen(data->auth_pass), 1); iks_md5_digest(md5, a1_h); iks_md5_reset(md5); iks_md5_hash(md5, (const unsigned char*)a1_h, 16, 0); iks_md5_hash(md5, (const unsigned char*)":", 1, 0); iks_md5_hash(md5, (const unsigned char*)nonce, iks_strlen(nonce), 0); iks_md5_hash(md5, (const unsigned char*)":", 1, 0); iks_md5_hash(md5, (const unsigned char*)cnonce, iks_strlen(cnonce), 1); iks_md5_print(md5, (char*)a1); iks_md5_reset(md5); iks_md5_hash(md5, (const unsigned char*)"AUTHENTICATE:xmpp/", 18, 0); iks_md5_hash(md5, (const unsigned char*)data->server, iks_strlen(data->server), 1); iks_md5_print(md5, (char*)a2); iks_md5_reset(md5); iks_md5_hash(md5, (const unsigned char*)a1, 32, 0); iks_md5_hash(md5, (const unsigned char*)":", 1, 0); iks_md5_hash(md5, (const unsigned char*)nonce, iks_strlen(nonce), 0); iks_md5_hash(md5, (const unsigned char*)":00000001:", 10, 0); iks_md5_hash(md5, (const unsigned char*)cnonce, iks_strlen(cnonce), 0); iks_md5_hash(md5, (const unsigned char*)":auth:", 6, 0); iks_md5_hash(md5, (const unsigned char*)a2, 32, 1); iks_md5_print(md5, (char*)response_value); iks_md5_delete(md5); i = iks_strlen(data->auth_username) + iks_strlen(realm) + iks_strlen(nonce) + iks_strlen(data->server) + CNONCE_LEN * 8 + 136; response = iks_malloc(i); if(!response) return NULL; sprintf(response, "username=\"%s\",realm=\"%s\",nonce=\"%s\"" ",cnonce=\"%s\",nc=00000001,qop=auth,digest-uri=\"" "xmpp/%s\",response=%s,charset=utf-8", data->auth_username, realm, nonce, cnonce, data->server, response_value); response_coded = iks_base64_encode(response, 0); if(response_coded) { x = iks_new("response"); iks_insert_cdata(x, response_coded, 0); iks_free(response_coded); } iks_free(response); return x; }