450 lines
10 KiB
C
450 lines
10 KiB
C
/****************************************************************************
|
|
|
|
mod_dav_pgsql (DASL) for apache 2.X
|
|
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
|
|
CopyRight(C) 2006 Netomi Inc. All Rights reserved.
|
|
Author : elenoa lazyfake (elenoa@solutionbox.co.kr)
|
|
|
|
$Id: share.c,v 1.8 2007/02/22 08:22:13 elenoa Exp $
|
|
|
|
Redistribution and use in source and binary forms, with or with out
|
|
modification, are not permitted in outside of SolutionBox Inc.
|
|
|
|
****************************************************************************/
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
|
|
#include <httpd.h>
|
|
#include <http_config.h>
|
|
#include <http_protocol.h>
|
|
#include <http_log.h>
|
|
#include <http_core.h> /* for ap_construct_url */
|
|
#include <http_request.h>
|
|
|
|
#include <apr_strings.h>
|
|
#include <apr_signal.h>
|
|
|
|
#include "dav_repos.h"
|
|
#include "dbms.h"
|
|
#include "util.h"
|
|
#include "share_common.h"
|
|
#include "share_account.h"
|
|
|
|
/* for user cache */
|
|
static struct shm_mgnt ucah_mgnt = {
|
|
NULL, NULL, SHM_UCAH, SHM_UCAH_LOCK, 0, 0
|
|
};
|
|
|
|
struct account_cache *g_ac;
|
|
static int maxcache = 0 ;
|
|
|
|
int dav_initialize_shared_account_cache(dav_repos_server_conf *dsc, server_rec *s, apr_pool_t *p)
|
|
{
|
|
if (dsc->user_cache <= 0) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "OPENDAV: initialize_shared_memory: "
|
|
"MaxUserCache <= 0 (%d)", dsc->user_cache);
|
|
return !OK;
|
|
}
|
|
|
|
maxcache = dsc->user_cache;
|
|
|
|
/* user cache : calculate shared memory size from user_cache value */
|
|
ucah_mgnt.size = (sizeof(struct account_cache) * dsc->user_cache);
|
|
g_ac = (struct account_cache *)dav_shared_get_new_memory(&ucah_mgnt, s, p, false);
|
|
if (!g_ac) return !OK;
|
|
|
|
return OK;
|
|
}
|
|
|
|
void dav_cleanup_shared_account_cache()
|
|
{
|
|
if (ucah_mgnt.shm) {
|
|
apr_shm_detach(ucah_mgnt.shm);
|
|
}
|
|
if (ucah_mgnt.lock) {
|
|
apr_global_mutex_destroy(ucah_mgnt.lock);
|
|
}
|
|
}
|
|
|
|
struct account_cache * dav_shared_ac_get_by_vol(const char * volume_name)
|
|
{
|
|
#ifndef __OPENDAV_SHARED_NOT_USE
|
|
int i;
|
|
|
|
if (!g_ac)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_ac_get_by_vol:: Account cache NULL. [%s]", volume_name);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#define AC_TIMEOUT 300
|
|
|
|
apr_global_mutex_lock(ucah_mgnt.lock);
|
|
|
|
for (i = 0; i < maxcache; i++)
|
|
{
|
|
if ((g_ac + i)->id[0] == '\0')
|
|
break;
|
|
|
|
if (!strcmp((g_ac + i)->svc_id, volume_name))
|
|
{
|
|
struct account_cache * retval = (g_ac + i);
|
|
|
|
// 2015.7.15 dadamin
|
|
// version 3.5부터 timeout 대신 fimnd 의해서 설정된 flag 값 참조
|
|
// 0 : 정상 , 1 : 삭제
|
|
if ((g_ac + i)->nFlag)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_ac_get_by_vol:: The [%s] service is deleted.", (g_ac + i)->svc_id);
|
|
retval = NULL;
|
|
}
|
|
|
|
apr_global_mutex_unlock(ucah_mgnt.lock);
|
|
return retval;
|
|
}
|
|
}
|
|
apr_global_mutex_unlock(ucah_mgnt.lock);
|
|
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_ac_get_by_vol:: The [%s] service not found.", volume_name);
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// NEW 2012-04-20 노경민
|
|
// dav_shared_ac_get_by_vol() 함수 상의 TIMEOUT 체크 기능으로 인해
|
|
// 무인증 관련 서비스의 대소문자 구분/무시 여부 확인 처리시...
|
|
// Cache 값 변경이 발생되지 않아... NULL 값이 반환되는 문제 발생..
|
|
// 따라서 이를 해결하기 위해 TIMEOUT 비교가 없는 함수를 추가함.
|
|
struct account_cache * dav_shared_ac_get_by_vol_not_timeout(const char * volume_name)
|
|
{
|
|
#ifndef __OPENDAV_SHARED_NOT_USE
|
|
int i;
|
|
|
|
if (!g_ac)
|
|
return NULL;
|
|
|
|
apr_global_mutex_lock(ucah_mgnt.lock);
|
|
|
|
for (i = 0; i < maxcache; i++)
|
|
{
|
|
if ((g_ac + i)->id[0] == '\0')
|
|
break;
|
|
|
|
// 2015.7.15 dadamin
|
|
// version 3.5부터 timeout 대신 fimnd 의해서 설정된 flag 값 참조
|
|
// 0 : 정상 , 1 : 삭제
|
|
if ((g_ac + i)->nFlag)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_ac_get_by_vol_not_timeout:: The [%s] service is deleted.", (g_ac + i)->svc_id);
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp((g_ac + i)->svc_id, volume_name))
|
|
{
|
|
struct account_cache * retval = (g_ac + i);
|
|
|
|
apr_global_mutex_unlock(ucah_mgnt.lock);
|
|
return retval;
|
|
}
|
|
}
|
|
apr_global_mutex_unlock(ucah_mgnt.lock);
|
|
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// 2017-03-08 CHG huibong
|
|
// - #28349 서비스 해지 처리된 경우 불필요한 로그가 인증시마다 발생, 이를 해결하기 위해 Flow 수정 처리.
|
|
//
|
|
struct account_cache *dav_shared_ac_get_by_tranid(char *seq)
|
|
{
|
|
#ifndef __OPENDAV_SHARED_NOT_USE
|
|
int i;
|
|
|
|
if (!g_ac)
|
|
return NULL;
|
|
|
|
apr_global_mutex_lock(ucah_mgnt.lock);
|
|
|
|
// 2015.7.15 dadamin
|
|
// version 3.5부터 timeout 대신 fimnd 의해서 설정된 flag 값 참조
|
|
// 0 : 정상 , 1 : 삭제
|
|
|
|
// 인증 처리 부분이므로 검색 속도는 최대한 빠르게 한다.
|
|
for (i = 0; i < maxcache; i++)
|
|
{
|
|
if ((g_ac + i)->id[0] == '\0')
|
|
break;
|
|
|
|
// 삭제된 서비스는 검색 조건에서 제거
|
|
if((g_ac + i)->nFlag)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 서비스 sequece 비교
|
|
if(!strcmp((g_ac + i)->tran_id, seq))
|
|
{
|
|
struct account_cache * retval = (g_ac + i);
|
|
apr_global_mutex_unlock(ucah_mgnt.lock);
|
|
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
// 삭제된 서비스 요청을 로깅 처리.
|
|
// - 요청량이 많지 않을 것이므로.. 응답이 늦어도 상관 없음.
|
|
// - 로깅 처리 후 NULL 반환
|
|
//for (i = 0; i < maxcache; i++)
|
|
//{
|
|
// if ((g_ac + i)->id[0] == '\0')
|
|
// break;
|
|
//
|
|
// // 삭제된 서비스
|
|
// if((g_ac + i)->nFlag)
|
|
// {
|
|
// // 삭제 또는 모르는 요청인 경우.. 전달받은 seq 값이 숫자로 변환되지 않고 요청된 그대로 들어오므로...
|
|
// // cache 된 정보와 seq 비교는 할 수 없다.
|
|
// // 따라서 그냥 해지된 서비스는 모두 로깅 처리한다.
|
|
// ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_ac_get_by_tranid:: service [%s] is deleted.", (g_ac + i)->svc_id);
|
|
//
|
|
// continue;
|
|
// }
|
|
//}
|
|
|
|
apr_global_mutex_unlock(ucah_mgnt.lock);
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// NEW 2012-03-20 노경민
|
|
// 각 서비스별 uri 에 대한 대소문자 구분, 무시 여부를 반환한다.
|
|
// 해당 반환값은 RCDB t_sms_sp_svc_product 테이블 uri_ignore_case 필드의 설정값을 확인하여 다음과 같이 반환처리한다.
|
|
// 0 : 대소문자 구분 ( 양방향 Default )
|
|
// 1 : 대소문자 무시
|
|
// -1 : 오류 발생.
|
|
int dav_shared_is_uri_ignore_case(const dav_resource * resource)
|
|
{
|
|
struct account_cache * ac = NULL;
|
|
dav_resource_private *info = NULL;
|
|
char *tranid;
|
|
|
|
if (resource == NULL || resource->info == NULL)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_is_uri_ignore_case: dav_resource NULL.");
|
|
return -1;
|
|
}
|
|
|
|
info = resource->info;
|
|
tranid = apr_psprintf(resource->pool, "%" APR_INT64_T_FMT "", info->user_id);
|
|
|
|
ac = dav_shared_ac_get_by_tranid(tranid);
|
|
|
|
// 해당 서비스 정보를 공유 메모리 상에서 확인하지 못한 경우
|
|
if (ac == NULL)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_is_uri_ignore_case: tranid[%s] uri ignore info not found.", tranid);
|
|
return -1;
|
|
}
|
|
|
|
return ac->is_ignorecase;
|
|
}
|
|
|
|
int dav_shared_is_uri_ignore_case_by_tranid(char *tranid)
|
|
{
|
|
struct account_cache * ac = NULL;
|
|
ac = dav_shared_ac_get_by_tranid(tranid);
|
|
|
|
// 해당 서비스 정보를 공유 메모리 상에서 확인하지 못한 경우
|
|
if (ac == NULL)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_is_uri_ignore_case_by_tranid: tranid[%s] uri ignore info not found.", tranid);
|
|
return -1;
|
|
}
|
|
|
|
return ac->is_ignorecase;
|
|
}
|
|
|
|
int dav_shared_is_uri_ignore_case_by_svcname(const char * svcname)
|
|
{
|
|
struct account_cache * ac = NULL;
|
|
ac = dav_shared_ac_get_by_vol_not_timeout(svcname);
|
|
|
|
// 해당 서비스 정보를 공유 메모리 상에서 확인하지 못한 경우
|
|
if (ac == NULL)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_shared_is_uri_ignore_case_by_svcname: svcname[%s] uri ignore info not found.", svcname);
|
|
return -1;
|
|
}
|
|
|
|
return ac->is_ignorecase;
|
|
}
|
|
|
|
static int dav_shared_ac_perform_find(char *haystack, char *__needle, int iscase)
|
|
{
|
|
char *needle = __needle;
|
|
int i, h = strlen(haystack), n = strlen(needle);
|
|
|
|
|
|
do {
|
|
// ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: Referer: find: needle %s/%s", needle, __needle);
|
|
|
|
__needle = needle;
|
|
|
|
if (h < n) goto next_time;
|
|
|
|
for (i = 0; i < (h - n + 1); i++) {
|
|
if (tolower(*(haystack + i)) == tolower(*needle)) {
|
|
#if 0
|
|
if (iscase == OK) {
|
|
#endif
|
|
if (!strncasecmp((haystack + i), needle, n)) {
|
|
goto match_n_next;
|
|
}
|
|
#if 0
|
|
}
|
|
else {
|
|
if (!strncmp((haystack + i), needle, n)) {
|
|
goto match_n_next;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
continue;
|
|
|
|
match_n_next:
|
|
if (i != 0 && *(haystack + i - 1) != '|')
|
|
continue;
|
|
|
|
if (*(haystack + i + n) != '|' && *(haystack + i + n) != '\0')
|
|
continue;
|
|
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: Referer: find: done?");
|
|
|
|
next_time:
|
|
needle = strchr(__needle, '.');
|
|
// ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: Referer: find: done? needle %x __needle %x", needle, __needle);
|
|
|
|
if (needle) {
|
|
needle++;
|
|
if (*needle == '\0') break;
|
|
n = strlen(needle);
|
|
}
|
|
} while (needle);
|
|
|
|
// ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: Referer: find: ALL done?");
|
|
|
|
return !OK;
|
|
}
|
|
|
|
#define IS_PERMIT_EMPTY_REFERER(ac) (strlen(ac->mode) > 4 && ac->mode[4] == '1')
|
|
int dav_shared_ac_check_referer(struct account_cache *ac, request_rec *r)
|
|
{
|
|
const char *referer = apr_table_get(r->headers_in, "Referer");
|
|
char *pszCopy, *pszUriCopy;
|
|
char *p, *p2, *p3, *q;
|
|
|
|
if ((!referer) || (NULL == referer) || (0 == strlen(referer)))
|
|
{
|
|
|
|
if (IS_PERMIT_EMPTY_REFERER(ac))
|
|
{
|
|
if (ac->permitted_referer[0] != '\0')
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: empty referer checking: referer is NULL, not permited.");
|
|
return !OK;
|
|
}
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
if (ac->permitted_referer[0] == '\0')
|
|
return OK;
|
|
|
|
pszCopy = apr_pstrdup(r->pool, referer);
|
|
if (!pszCopy)
|
|
return OK;
|
|
|
|
if ((p = strstr(pszCopy, "://")))
|
|
p += 3;
|
|
else
|
|
p = pszCopy;
|
|
|
|
p2 = strchr(p, '/');
|
|
p3 = strchr(p, ':');
|
|
|
|
if (p2 == NULL)
|
|
{
|
|
if (p3 == NULL)
|
|
{
|
|
if (IS_PERMIT_EMPTY_REFERER(ac))
|
|
{
|
|
if (ac->permitted_referer[0] != '\0')
|
|
;
|
|
else
|
|
return OK;
|
|
}
|
|
else
|
|
return OK;
|
|
}
|
|
else
|
|
{
|
|
q = p3;
|
|
*q = '\0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p3 == NULL)
|
|
q = p2;
|
|
else if (p2 < p3)
|
|
q = p2;
|
|
else
|
|
q = p3;
|
|
|
|
*q = '\0';
|
|
}
|
|
|
|
|
|
pszUriCopy = apr_pstrdup(r->pool, r->uri);
|
|
q = pszUriCopy;
|
|
|
|
if ((p2 = strrchr(q, '.')))
|
|
q = p2 + 1;
|
|
else
|
|
q = NULL;
|
|
|
|
if (ac->permitted_extend[0] != '\0')
|
|
{
|
|
if (!q)
|
|
return OK;
|
|
|
|
if (dav_shared_ac_perform_find(ac->permitted_extend, q, !OK) == !OK)
|
|
return OK;
|
|
}
|
|
|
|
if (ac->permitted_referer[0] != '\0')
|
|
{
|
|
if (dav_shared_ac_perform_find(ac->permitted_referer, p, OK) == !OK)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: referer: uri %s, extension %s, permitted %s !!!!!"
|
|
, p, (ac->permitted_extend[0] != '\0' ? ac->permitted_extend : "NONE"), ac->permitted_referer);
|
|
|
|
return !OK;
|
|
}
|
|
}
|
|
|
|
return OK;
|
|
}
|