📄 mech_digest_md5.c
字号:
md5_init(&md5); md5_append(&md5, "AUTHENTICATE:", 13); md5_append(&md5, "xmpp/", 5); /* !!! make this configurable */ md5_finish(&md5, hash); /* A2 */ hex_from_raw(hash, 16, ha2); log_debug(ZONE, "HEX(H(A2)) = %s", ha2); md5_init(&md5); md5_append(&md5, ha1, 32); md5_append(&md5, ":", 1); md5_append(&md5, nonce, strlen(nonce)); md5_append(&md5, ":", 1); md5_append(&md5, "00000001", 8); md5_append(&md5, ":", 1); md5_append(&md5, cnonce, 40); md5_append(&md5, ":auth:", 6); md5_append(&md5, ha2, 32); md5_finish(&md5, hash); /* KD(HA1, foo, HA2) */ hex_from_raw(hash, 16, hrsp); log_debug(ZONE, "response is %s", hrsp); /* !!! generate rspauth and save it for later so we can validate */ p = pool_new(); s = spool_new(p); c = _opt_quote(sd->authnid); spooler(s, "username=", c, ",", s); free(c); c = _opt_quote(nonce); spooler(s, "nonce=", c, ",", s); free(c); c = _opt_quote(cnonce); spooler(s, "cnonce=", c, ",", s); free(c); if(sd->authzid != NULL) { c = _opt_quote(sd->authzid); spooler(s, "authzid=", c, ",", s); free(c); } if(realm != NULL) { c = _opt_quote(realm); spooler(s, "realm=", c, ",", s); free(c); } spooler(s, "nc=00000001,qop=auth,digest-uri=\"xmpp/\",charset=utf-8,response=", hrsp, s); *resp = strdup(spool_print(s)); *resplen = strlen(*resp); pool_free(p); xhash_free(attrs); free(cnonce); log_debug(ZONE, "generated initial response: %.*s", *resplen, *resp); sd->mech_data = (void *) 1; return sd_CONTINUE;}static int _digest_md5_server_start(scod_mech_t mech, scod_t sd, const char *resp, int resplen, char **chal, int *challen) { digest_md5_t md; pool p; spool s; char *c, *nonce; log_debug(ZONE, "DIGEST-MD5 server start"); p = pool_new(); md = (digest_md5_t) pmalloco(p, sizeof(struct _digest_md5_st)); md->p = p; sd->mech_data = md; p = pool_new(); s = spool_new(p); if(sd->realm != NULL) { c = _opt_quote(sd->realm); spooler(s, "realm=", c, ",", s); free(c); } nonce = _digest_md5_gen_nonce(); md->nonce = pstrdup(md->p, nonce); free(nonce); c = _opt_quote(md->nonce); spooler(s, "nonce=", c, ",qop=\"auth\",charset=utf-8,algorithm=md5-sess", s); free(c); *chal = strdup(spool_print(s)); *challen = strlen(*chal); pool_free(p); log_debug(ZONE, "generated initial challenge: %.*s", *challen, *chal); return sd_CONTINUE;}static int _digest_md5_server_step(scod_mech_t mech, scod_t sd, const char *resp, int resplen, char **chal, int *challen) { digest_md5_t md = (digest_md5_t) sd->mech_data; xht attrs, sub; char *key, *username, *realm, *nonce, *cnonce, *nc, *qop, *digest_uri, *response, *charset, *pass, buf[257], *c, authzid[3072]; int err; md5_state_t md5; md5_byte_t hash[16]; char ha1[33], ha2[33], hrsp[33]; struct _scod_cb_creds_st creds; log_debug(ZONE, "DIGEST-MD5 server step; response: %.*s", resplen, resp); if(md->step == 1) { /* we're done */ pool_free(md->p); sd->mech_data = NULL; return sd_SUCCESS; } username = realm = nonce = cnonce = nc = qop = digest_uri = response = charset = NULL; authzid[0] = '\0'; attrs = _digest_md5_parse_options(resp, resplen); if(xhash_iter_first(attrs)) do { xhash_iter_get(attrs, (const char **) &key, (void **) &sub); log_debug(ZONE, "extracting '%s'", key); if(xhash_iter_first(sub)) { if(strcmp(key, "username") == 0) xhash_iter_get(sub, (const char **) &username, NULL); else if(strcmp(key, "realm") == 0) xhash_iter_get(sub, (const char **) &realm, NULL); else if(strcmp(key, "nonce") == 0) xhash_iter_get(sub, (const char **) &nonce, NULL); else if(strcmp(key, "cnonce") == 0) xhash_iter_get(sub, (const char **) &cnonce, NULL); else if(strcmp(key, "nc") == 0) xhash_iter_get(sub, (const char **) &nc, NULL); else if(strcmp(key, "qop") == 0) xhash_iter_get(sub, (const char **) &qop, NULL); else if(strcmp(key, "digest-uri") == 0) xhash_iter_get(sub, (const char **) &digest_uri, NULL); else if(strcmp(key, "response") == 0) xhash_iter_get(sub, (const char **) &response, NULL); else if(strcmp(key, "charset") == 0) xhash_iter_get(sub, (const char **) &charset, NULL); else if(strcmp(key, "authzid") == 0) { xhash_iter_get(sub, (const char **) &c, NULL); strncpy(authzid, c, sizeof(authzid)); } } } while(xhash_iter_next(attrs)); err = sd_SUCCESS; if(username == NULL || nonce == NULL || cnonce == NULL || nc == NULL || qop == NULL || digest_uri == NULL || response == NULL) err = sd_auth_MALFORMED_DATA; else if(strcmp(nonce, md->nonce) != 0) err = sd_auth_MISMATCH; else if(strcmp(qop, "auth") != 0) err = sd_auth_NOT_OFFERED; if(err != sd_SUCCESS) { log_debug(ZONE, "returning error %d", err); xhash_free(attrs); pool_free(md->p); sd->mech_data = NULL; return err; } /* !!! verify realm? */ creds.authnid = username; creds.realm = realm; creds.pass = NULL; pass = buf; if((mech->ctx->cb)(sd, sd_cb_GET_PASS, &creds, (void **) &pass, mech->ctx->cbarg) != 0) { log_debug(ZONE, "user not found (or some other error getting password), failing"); xhash_free(attrs); pool_free(md->p); sd->mech_data = NULL; return sd_auth_USER_UNKNOWN; } md->cnonce = pstrdup(md->p, cnonce); md->nc = pstrdup(md->p, nc); md5_init(&md5); md5_append(&md5, username, strlen(username)); md5_append(&md5, ":", 1); if(realm != NULL) md5_append(&md5, realm, strlen(realm)); md5_append(&md5, ":", 1); if(pass != NULL) md5_append(&md5, pass, strlen(pass)); md5_finish(&md5, hash); md5_init(&md5); md5_append(&md5, hash, 16); md5_append(&md5, ":", 1); md5_append(&md5, md->nonce, strlen(md->nonce)); md5_append(&md5, ":", 1); md5_append(&md5, md->cnonce, strlen(md->cnonce)); if(authzid[0] != '\0') { md5_append(&md5, ":", 1); md5_append(&md5, authzid, strlen(authzid)); } md5_finish(&md5, hash); /* A1 */ hex_from_raw(hash, 16, ha1); log_debug(ZONE, "HEX(H(A1)) = %s", ha1); md5_init(&md5); md5_append(&md5, "AUTHENTICATE:", 13); md5_append(&md5, digest_uri, strlen(digest_uri)); md5_finish(&md5, hash); /* A2 */ hex_from_raw(hash, 16, ha2); log_debug(ZONE, "HEX(H(A2)) = %s", ha2); md5_init(&md5); md5_append(&md5, ha1, 32); md5_append(&md5, ":", 1); md5_append(&md5, nonce, strlen(nonce)); md5_append(&md5, ":", 1); md5_append(&md5, nc, strlen(nc)); md5_append(&md5, ":", 1); md5_append(&md5, cnonce, strlen(cnonce)); md5_append(&md5, ":auth:", 6); md5_append(&md5, ha2, 32); md5_finish(&md5, hash); /* KD(HA1, foo, HA2) */ hex_from_raw(hash, 16, hrsp); log_debug(ZONE, "our response is %s, theirs is %s", hrsp, response); if(strcmp(hrsp, response) != 0) { log_debug(ZONE, "not matched, denied"); xhash_free(attrs); pool_free(md->p); sd->mech_data = NULL; return sd_auth_AUTH_FAILED; } log_debug(ZONE, "matched, they're authenticated"); creds.authnid = username; creds.realm = realm; creds.pass = NULL; creds.authzid = authzid; if((mech->ctx->cb)(sd, sd_cb_CHECK_AUTHZID, &creds, NULL, mech->ctx->cbarg) != 0) { log_debug(ZONE, "authzid is invalid (app policy said so)"); xhash_free(attrs); pool_free(md->p); sd->mech_data = NULL; return sd_auth_AUTHZID_POLICY; } sd->authzid = strdup(creds.authzid); md5_init(&md5); md5_append(&md5, ":", 1); md5_append(&md5, digest_uri, strlen(digest_uri)); md5_finish(&md5, hash); /* rspauth A2 */ hex_from_raw(hash, 16, ha2); log_debug(ZONE, "HEX(H(rspauth A2)) = %s", ha2); md5_init(&md5); md5_append(&md5, ha1, 32); md5_append(&md5, ":", 1); md5_append(&md5, nonce, strlen(nonce)); md5_append(&md5, ":", 1); md5_append(&md5, nc, strlen(nc)); md5_append(&md5, ":", 1); md5_append(&md5, cnonce, strlen(cnonce)); md5_append(&md5, ":auth:", 6); md5_append(&md5, ha2, 32); md5_finish(&md5, hash); /* KD(HA1, foo, HA2) */ hex_from_raw(hash, 16, hrsp); log_debug(ZONE, "rspauth: %s", hrsp); *chal = (char *) malloc(sizeof(char) * 41); snprintf(*chal, 41, "rspauth=%s", hrsp); *challen = 40; log_debug(ZONE, "generated final challenge: %.*s", *challen, *chal); md->step = 1; xhash_free(attrs); return sd_CONTINUE;}static void _digest_md5_free(scod_mech_t mech) { xhash_free((xht) mech->private);}int scod_mech_digest_md5_init(scod_mech_t mech) { log_debug(ZONE, "initialising DIGEST-MD5 mechanism"); mech->name = "DIGEST-MD5"; mech->flags = sd_flag_GET_PASS; mech->client_start = _digest_md5_client_start; mech->client_step = _digest_md5_client_step; mech->server_start = _digest_md5_server_start; mech->server_step = _digest_md5_server_step; mech->free = _digest_md5_free; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -