📄 httpda.c
字号:
static int http_da_preparerecv(struct soap *soap, const char *buf, size_t len){ struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; md5_handler(soap, &data->context, MD5_UPDATE, (char*)buf, len); if (data->fpreparerecv) return data->fpreparerecv(soap, buf, len); return SOAP_OK;}static int http_da_disconnect(struct soap *soap){ struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return SOAP_PLUGIN_ERROR; md5_handler(soap, &data->context, MD5_FINAL, data->digest, 0); soap->fpreparerecv = data->fpreparerecv; soap->fdisconnect = data->fdisconnect; if (soap->fdisconnect) return soap->fdisconnect(soap); return SOAP_OK;}/******************************************************************************\ * * Client-side digest authentication state management *\******************************************************************************/void http_da_save(struct soap *soap, struct http_da_info *info, const char *realm, const char *userid, const char *passwd){ struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return; info->authrealm = soap->authrealm = soap_strdup(NULL, realm); info->userid = soap->userid = soap_strdup(NULL, userid); info->passwd = soap->passwd = soap_strdup(NULL, passwd); info->nonce = soap_strdup(NULL, data->nonce); info->opaque = soap_strdup(NULL, data->opaque); info->qop = soap_strdup(NULL, data->qop); info->alg = soap_strdup(NULL, data->alg);}void http_da_restore(struct soap *soap, struct http_da_info *info){ struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return; soap->authrealm = info->authrealm; soap->userid = info->userid; soap->passwd = info->passwd; data->nonce = info->nonce; data->opaque = info->opaque; data->qop = info->qop; data->alg = info->alg;}void http_da_release(struct soap *soap, struct http_da_info *info){ struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); if (!data) return; soap->authrealm = NULL; soap->userid = NULL; soap->passwd = NULL; data->nonce = NULL; data->opaque = NULL; data->qop = NULL; data->alg = NULL; if (info->authrealm) { free(info->authrealm); info->authrealm = NULL; } if (info->userid) { free(info->userid); info->userid = NULL; } if (info->passwd) { free(info->passwd); info->passwd = NULL; } if (info->nonce) { free(info->nonce); info->nonce = NULL; } if (info->opaque) { free(info->opaque); info->opaque = NULL; } if (info->qop) { free(info->qop); info->qop = NULL; } if (info->alg) { free(info->alg); info->alg = NULL; }}/******************************************************************************\ * * Server-side digest authentication verification *\******************************************************************************/int http_da_verify_post(struct soap *soap, char *passwd){ return http_da_verify_method(soap, "POST", passwd);}int http_da_verify_get(struct soap *soap, char *passwd){ return http_da_verify_method(soap, "GET", passwd);}static int http_da_verify_method(struct soap *soap, char *method, char *passwd){ struct http_da_data *data = (struct http_da_data*)soap_lookup_plugin(soap, http_da_id); char HA1[33], entityHAhex[33], response[33]; if (!data) return SOAP_ERR; /* reject if none or basic authentication was used */ if (!soap->authrealm || !soap->userid || soap->passwd) /* passwd is set when basic auth is used */ return SOAP_ERR; /* require at least qop="auth" to prevent replay attacks */ if (!data->qop) return SOAP_ERR; if (http_da_session_update(soap->authrealm, data->nonce, data->opaque, data->cnonce, data->ncount)) return SOAP_ERR; http_da_calc_HA1(soap, &data->context, NULL, soap->userid, soap->authrealm, passwd, data->nonce, data->cnonce, HA1); if (!soap_tag_cmp(data->qop, "auth-int")) soap_s2hex(soap, (unsigned char*)data->digest, entityHAhex, 16); http_da_calc_response(soap, &data->context, HA1, data->nonce, data->ncount, data->cnonce, data->qop, method, soap->path, entityHAhex, response);#ifdef SOAP_DEBUG fprintf(stderr, "Verifying client response=%s with calculated digest=%s\n", data->response, response);#endif /* check digest response values */ if (strcmp(data->response, response)) return SOAP_ERR; return SOAP_OK;}/******************************************************************************\ * * Digest authentication session database management *\******************************************************************************/static void http_da_session_start(const char *realm, const char *nonce, const char *opaque){ struct http_da_session *session; time_t now = time(NULL); if (now % 10 == 0) /* don't do this all the time to improve efficiency */ http_da_session_cleanup();#ifdef SOAP_DEBUG fprintf(stderr, "Starting session realm=%s nonce=%s\n", realm, nonce);#endif MUTEX_LOCK(http_da_session_lock); session = (struct http_da_session*)malloc(sizeof(struct http_da_session)); if (session) { session->next = http_da_session; session->modified = now; session->realm = soap_strdup(NULL, realm); session->nonce = soap_strdup(NULL, nonce); session->opaque = soap_strdup(NULL, opaque); session->nc = 0; http_da_session = session; } MUTEX_UNLOCK(http_da_session_lock);}static int http_da_session_update(const char *realm, const char *nonce, const char *opaque, const char *cnonce, const char *ncount){ struct http_da_session *session; if (!realm || !nonce || !opaque || !cnonce || !ncount) return SOAP_ERR;#ifdef SOAP_DEBUG fprintf(stderr, "Updating session realm=%s nonce=%s\n", realm, nonce);#endif MUTEX_LOCK(http_da_session_lock); for (session = http_da_session; session; session = session->next) if (!strcmp(session->realm, realm) && !strcmp(session->nonce, nonce) && !strcmp(session->opaque, opaque)) break; if (session) { unsigned long nc = soap_strtoul(ncount, NULL, 16); if (session->nc >= nc) { session->modified = 0; /* replay attack: terminate session */ session = NULL; } else { session->nc = nc; session->modified = time(NULL); } } MUTEX_UNLOCK(http_da_session_lock); if (!session) return SOAP_ERR; return SOAP_OK;}static void http_da_session_cleanup(){ struct http_da_session **session; time_t now = time(NULL); MUTEX_LOCK(http_da_session_lock); session = &http_da_session; while (*session) { if ((*session)->modified + HTTP_DA_SESSION_TIMEOUT < now) { struct http_da_session *p = *session;#ifdef SOAP_DEBUG fprintf(stderr, "Deleting session realm=%s nonce=%s\n", p->realm, p->nonce);#endif if (p->realm) free(p->realm); if (p->nonce) free(p->nonce); if (p->opaque) free(p->opaque); *session = p->next; free(p); } else session = &(*session)->next; } MUTEX_UNLOCK(http_da_session_lock);}/******************************************************************************\ * * Calculate hex nonce and opaque values *\******************************************************************************/void http_da_calc_nonce(struct soap *soap, char nonce[HTTP_DA_NONCELEN]){ static short count = 0xCA53; sprintf(nonce, "%8.8x%4.4hx%8.8x", (int)time(NULL), count++, soap_random);}void http_da_calc_opaque(struct soap *soap, char opaque[HTTP_DA_OPAQUELEN]){ sprintf(opaque, "%8.8x", soap_random);}/******************************************************************************\ * * Calculate HA1, HA2, and response digest as per RFC 2617 specification *\******************************************************************************/static void http_da_calc_HA1(struct soap *soap, void **context, char *alg, char *userid, char *realm, char *passwd, char *nonce, char *cnonce, char HA1hex[33]){ char HA1[16]; md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, userid, strlen(userid)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, realm, strlen(realm)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, passwd, strlen(passwd)); md5_handler(soap, context, MD5_FINAL, HA1, 0); if (alg && !soap_tag_cmp(alg, "MD5-sess")) { md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, HA1, 16); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, nonce, strlen(nonce)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, cnonce, strlen(cnonce)); md5_handler(soap, context, MD5_FINAL, HA1, 0); }; soap_s2hex(soap, (unsigned char*)HA1, HA1hex, 16);};static void http_da_calc_response(struct soap *soap, void **context, char HA1hex[33], char *nonce, char *ncount, char *cnonce, char *qop, char *method, char *uri, char entityHAhex[33], char response[33]){ char HA2[16], HA2hex[33], responseHA[16]; md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, method, strlen(method)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, uri, strlen(uri)); if (!soap_tag_cmp(qop, "auth-int")) { md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, entityHAhex, 32); } md5_handler(soap, context, MD5_FINAL, HA2, 0); soap_s2hex(soap, (unsigned char*)HA2, HA2hex, 16); md5_handler(soap, context, MD5_INIT, NULL, 0); md5_handler(soap, context, MD5_UPDATE, HA1hex, 32); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, nonce, strlen(nonce)); md5_handler(soap, context, MD5_UPDATE, ":", 1); if (qop && *qop) { md5_handler(soap, context, MD5_UPDATE, ncount, strlen(ncount)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, cnonce, strlen(cnonce)); md5_handler(soap, context, MD5_UPDATE, ":", 1); md5_handler(soap, context, MD5_UPDATE, qop, strlen(qop)); md5_handler(soap, context, MD5_UPDATE, ":", 1); } md5_handler(soap, context, MD5_UPDATE, HA2hex, 32); md5_handler(soap, context, MD5_FINAL, responseHA, 0); soap_s2hex(soap, (unsigned char*)responseHA, response, 16);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -