Files
interactive/fhs/sh-opendav/auth.c
2026-08-07 17:38:18 +09:00

2097 lines
57 KiB
C

/****************************************************************************
mod_dav_pgsql (DASL) for apache 2.X
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
Author : sean kim (sean@solutionbox.co.kr)
$Id: auth.c,v 1.4 2007/03/19 08:43:11 elenoa Exp $
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of SolutionBox Inc.
****************************************************************************/
#include <ctype.h>
#include <mcrypt.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 <http_connection.h>
#include <apr_strings.h>
#include <apr_hash.h>
#include <apr_base64.h>
#include "dav_repos.h"
#include "dbms.h"
#include "util.h"
#include "share_common.h"
#include "share_account.h"
#include "share_anonymous.h"
// 2018-01-25 huibong 토토지원 과금 IP 확인용 임시 코드 , inet_ntop()
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MaxSizeOfQueryBuffer 1024
/* Note: the "dav_repos" prefix is mandatory */
extern module AP_MODULE_DECLARE_DATA dav_repos_module;
int dav_auth_user(request_rec *r, apr_off_t content, apr_off_t *permitted);
/* Elenoa 2005.12.28 : SP-Authrization START */
/* Copy and Modify : ap_get_basic_auth_pw from server/protocol.c */
/* Cannot use ap_pbase64decode. remake ap_get_basic_auth_pw */
static int dav_auth_get_pw_str(request_rec *r, const char **pw)
{
const char *auth_line = apr_table_get(r->headers_in,
(PROXYREQ_PROXY == r->proxyreq)
? "Proxy-Authorization"
: "Authorization");
const char *t;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_get_pw_str: authline: %s", auth_line);
#endif
if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
return DECLINED;
if (!ap_auth_name(r)) {
ap_log_error(APLOG_MARK, APLOG_ERR,
0, NULL, "need AuthName: %s", r->uri);
return HTTP_INTERNAL_SERVER_ERROR;
}
if (!auth_line) {
ap_note_basic_auth_failure(r);
return HTTP_UNAUTHORIZED;
}
if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
/* Client tried to authenticate using wrong auth scheme */
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"client used wrong authentication scheme: %s", r->uri);
ap_note_basic_auth_failure(r);
return HTTP_UNAUTHORIZED;
}
while (*auth_line == ' ' || *auth_line == '\t') {
auth_line++;
}
*pw = auth_line;
return OK;
}
#ifdef __OPENDAV_DEBUG__
void binary_dump(char *szBin, int len)
{
int i;
char outbuf[1024];
outbuf[0] = '\0';
for (i = 0; i < len; i++) {
sprintf(outbuf, "%s %2X", outbuf, (unsigned char)(*((unsigned char *)szBin + i)));
if (((i + 1) % 16) == 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s", outbuf);
outbuf[0] = '\0';
}
}
if (strlen(outbuf) > 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s", outbuf);
}
}
#endif
/* OLD Authorization */
static int dav_auth_sp_old(request_rec *r, char *pszPW, int len, struct account_cache *pac)
{
char *pszResult = NULL;
char *pszCUser = NULL;
char *pszCExpire = NULL;
char *pszCPW = NULL;
char *p1, *p2, *p3;
MCRYPT mcrypt = NULL;
time_t now = time(0);
char *pszKey;
char *pszIV;
char *pszDBPW;
if (!pszPW || !pac)
return !OK;
pszKey = pac->pk;
pszIV = pac->iv;
pszDBPW = pac->pass;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG3("dav_auth_sp_old::pszPW=%s (%d) pszKey=%s",
pszPW, len, pszKey);
DBG1("dav_auth_sp_old::pszIV=%s", pszIV);
#endif
//apr_global_mutex_lock(db_global_lock);
mcrypt = mcrypt_module_open(MCRYPT_BLOWFISH, NULL, MCRYPT_CBC, NULL);
if (mcrypt == MCRYPT_FAILED) {
#ifdef __OPENDAV_OLDAUTH_LOG__
ap_log_error(APLOG_MARK, APLOG_ERR,
0, NULL, "dav_auth_sp_old: mcrypt open failed");
#endif
//apr_global_mutex_unlock(db_global_lock);
return !OK;
}
if (mcrypt_generic_init(mcrypt, pszKey, KEY_LENGTH, pszIV) < 0) {
#ifdef __OPENDAV_OLDAUTH_LOG__
ap_log_error(APLOG_MARK, APLOG_ERR,
0, NULL, "dav_auth_sp_old: mcrypt init failed");
#endif
//apr_global_mutex_unlock(db_global_lock);
return !OK;
}
if (mdecrypt_generic(mcrypt, pszPW, len) < 0) {
#ifdef __OPENDAV_OLDAUTH_LOG__
ap_log_error(APLOG_MARK, APLOG_ERR,
0, NULL, "dav_auth_sp_old: mdecrypt failed");
#endif
//apr_global_mutex_unlock(db_global_lock);
return !OK;
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_old::decrypted pszPW=%s", pszPW);
//DBG1("dav_auth_sp_old::TEST %s", get_hashed_filepath("sp"));
#endif
mcrypt_generic_deinit(mcrypt);
//apr_global_mutex_unlock(db_global_lock);
/* Elenoa : 2006. 4. 6 :
* fix problem '-' char in userid and product name */
/*
pszCUser = ap_getword_nulls_nc (r->pool, &pszPW, '-');
pszCPW = ap_getword_nulls_nc (r->pool, &pszPW, '-');
pszCExpire = pszPW;
*/
p1 = strchr(pszPW, '@');
p2 = strrchr(pszPW, '-');
if (!p1 || !p2) {
return !OK;
}
p1++;
p3 = p2 - 1;
while (p3 > p1 && *p3 != '-') p3--;
if (p3 == p1) {
#ifdef __OPENDAV_OLDAUTH_LOG__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_old: password format not matched: case 2");
#endif
return !OK;
}
pszCUser = apr_pstrndup(r->pool, pszPW, (p3 - pszPW));
p3++;
pszCPW = apr_pstrndup(r->pool, p3, (p2 - p3));
pszCExpire = p2 + 1;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_sp_old::now=%d expire=%s", now, pszCExpire);
#endif
if (atoi(pszCExpire) < now) {
#ifdef __OPENDAV_OLDAUTH_LOG__
if (atoi(pszCExpire) != 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_old: timeout: server %d client %s",
now, pszCExpire);
}
#endif
return !OK;
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_old::pszPW %s", pszPW);
DBG3("dav_auth_sp_old::pszCUser %s pszCPW %s pszCExpire %s",
pszCUser, pszCPW, pszCExpire);
#endif
pszResult = apr_pstrcat(r->pool, pszCUser, pszDBPW, pszCExpire, NULL);
// CHG 2010-08-10 huibong
// get_hashed_filepath 함수정의 변경에 따른 코드 수정
char szHashResult[APR_MD5_DIGESTSIZE * 2 + 1];
if( get_hashed_filepath( pszResult, szHashResult, sizeof(szHashResult) ) == false )
{
// Clear array
memset( szHashResult, 0x00, sizeof(szHashResult));
// Write error log
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_auth_sp_old:get_hashed_filepath return false.[%s][%s][%zu]"
, pszResult, szHashResult, sizeof(szHashResult));
}
#ifdef __OPENDAV_DEBUG_AUTH__
//DBG3("dav_auth_sp_old::pszResult=%s,hash=%s,pszCPW=%s", pszResult, get_hashed_filepath(pszResult), pszCPW);
DBG3("dav_auth_sp_old::pszResult=%s,hash=%s,pszCPW=%s", pszResult, szHashResult, pszCPW);
#endif
//if (strcmp(get_hashed_filepath(pszResult), pszCPW))
if (strcmp(szHashResult, pszCPW))
{
#ifdef __OPENDAV_OLDAUTH_LOG__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_auth_sp_old: auth string failed: server %s client %s", szHashResult, pszCPW);
#endif
return !OK;
}
return OK;
}
//pac->pk, pac->iv, pac->pass
/* NEW Authorization */
static int dav_auth_sp_new(request_rec *r, char *pszPW, int len, struct account_cache *pac)
{
char *pszResult = NULL;
char *pszCUser = NULL;
char *pszCExpire = NULL;
char *pszCPW = NULL;
char *p1, *p2, *p3;
MCRYPT mcrypt = NULL;
time_t now = time(0);
time_t csdk_time = 0;
char hashed_uri[16];
char hashed_session_dump[33];
// CHG 2011-12-01 huibong
// apr_md5() 함수 형식에 맞도록 변수 타입 수정 처리
//char hashed_current_uri[16], *escaped_request;
unsigned char hashed_current_uri[16];
char *escaped_request;
int i;
char *pszKey;
char *pszIV;
char *pszDBPW;
//if (!pszPW || !pszKey || !pszIV || !pszDBPW)
if (!pszPW || !pac)
return !OK;
pszKey = pac->pk;
pszIV = pac->iv;
pszDBPW = pac->pass;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG3("dav_auth_sp_new::pszPW=%s (%d) pszKey=%s",
pszPW, len, pszKey);
DBG1("dav_auth_sp_new::pszIV=%s", pszIV);
#endif
/* compare length. (timestamp, session, uri) */
if (len <= (4 + 16 + 16)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: length too small (< 36)");
return !OK;
}
/* Elenoa: 2006. 7. 11: Add New Authrization START */
/* decrypt tea */
tea_decrypt(pszPW, len);
#ifdef __OPENDAV_DEBUG__
binary_dump(pszPW, len);
#endif
/* get time */
csdk_time = (time_t)*((int *)pszPW);
pszPW += 4;
/* compare timestamp (from CSDK) */
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_sp_new::now=%d expire(CSDK)=%d", now, csdk_time);
#endif
#define CSDK_TIMEOUT 3600
if ((csdk_time + CSDK_TIMEOUT) < now ||
(csdk_time - CSDK_TIMEOUT) > now) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: timeout (csdk): server %d client %d",
(int)now, (int)csdk_time);
return !OK;
}
/* get session (hashed) */
for (i = 0; i < 16; i++) {
sprintf((hashed_session_dump + (i << 1)), "%02x", *((unsigned char *)(pszPW + i)));
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_new::session %s", hashed_session_dump);
#endif
pszPW += 16;
/* get uri (hashed) */
memcpy(hashed_uri, pszPW, 16);
pszPW += 16;
/* compare md5'd file path */
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_sp_new::the_request=%s uri=%s", r->the_request, r->uri);
#endif
{
const char *ll = r->the_request;
// CHG 2019-08-28 huibong gcc compile warning 수정 (#32780)
ap_getword_white(r->pool, &ll); // method
char *uri = ap_getword_white(r->pool, &ll); // uri
escaped_request = apr_pstrdup(r->pool, uri);
}
ap_unescape_url(escaped_request);
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_new::escaped_request=%s", escaped_request);
#endif
apr_md5(hashed_current_uri, (const unsigned char *)escaped_request, strlen(escaped_request));
#ifdef __OPENDAV_DEBUG_AUTH__
DBG3("dav_auth_sp_new::hashed_uri=%x inputed hash=%x uri=%s",
*((int *)hashed_current_uri), *((int *)hashed_uri), escaped_request);
#endif
if (memcmp(hashed_current_uri, hashed_uri, 16)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: uri not match: server %s client %s",
hashed_current_uri, hashed_uri);
return !OK;
}
/* before decrypt mcrypt-blowfish, decrypt base64 first. */
{
char *decoded;
int dec_len;
char *p;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_new::pszPW=%s", pszPW);
#ifdef __OPENDAV_DEBUG__
binary_dump(pszPW, strlen(pszPW));
#endif
#endif
decoded = (char *) apr_palloc(r->pool, 8 + (dec_len = apr_base64_decode_len(pszPW)));
memset(decoded, 0, dec_len + 7);
dec_len = apr_base64_decode(decoded, pszPW);
pszPW = decoded;
len = dec_len;
/* skip til ':' char */
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_sp_new::before skip pszPW=%s(%d)", pszPW, len);
#endif
if ((p = strchr(pszPW, ':'))) {
p++;
len -= (p - pszPW); pszPW = p;
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_sp_new::before decrypt pszPW=%s(%d)", pszPW, len);
#endif
}
/* Elenoa: 2006. 7. 11: Add New Authrization END */
/* decrypt mcrypt-blowfish */
//apr_global_mutex_lock(db_global_lock);
mcrypt = mcrypt_module_open(MCRYPT_BLOWFISH, NULL, MCRYPT_CBC, NULL);
if (mcrypt == MCRYPT_FAILED) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: mcrypt open failed");
//apr_global_mutex_unlock(db_global_lock);
return !OK;
}
if (mcrypt_generic_init(mcrypt, pszKey, KEY_LENGTH, pszIV) < 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: mcrypt init failed");
//apr_global_mutex_unlock(db_global_lock);
return !OK;
}
if (mdecrypt_generic(mcrypt, pszPW, len) < 0) {
ap_log_error(APLOG_MARK, APLOG_ERR,
0, NULL, "dav_auth_sp_new: mdecrypt failed");
//apr_global_mutex_unlock(db_global_lock);
return !OK;
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_new::decrypted pszPW=%s", pszPW);
//DBG1("dav_auth_sp_new::TEST %s", get_hashed_filepath("sp"));
#endif
mcrypt_generic_deinit(mcrypt);
//apr_global_mutex_unlock(db_global_lock);
/* Elenoa : 2006. 4. 6 :
* fix problem '-' char in userid and product name */
/* parse user id, user pass, timestamp */
p1 = strchr(pszPW, '@');
p2 = strrchr(pszPW, '-');
if (!p1 || !p2) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: password format not matched: case 1");
return !OK;
}
p1++;
p3 = p2 - 1;
while (p3 > p1 && *p3 != '-') p3--;
if (p3 == p1) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: password format not matched: case 2");
return !OK;
}
pszCUser = apr_pstrndup(r->pool, pszPW, (p3 - pszPW));
p3++;
pszCPW = apr_pstrndup(r->pool, p3, (p2 - p3));
pszCExpire = p2 + 1;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_sp_new::now=%d expire=%s", now, pszCExpire);
#endif
/* compare expire date (from SSDK) */
if (atoi(pszCExpire) < now) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_sp_new: timeout: server %d client %s",
(int)now, pszCExpire);
return !OK;
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_sp_new::pszPW %s", pszPW);
DBG3("dav_auth_sp_new::pszCUser %s pszCPW %s pszCExpire %s",
pszCUser, pszCPW, pszCExpire);
#endif
pszResult = apr_pstrcat(r->pool, pszCUser, pszDBPW, pszCExpire, NULL);
// CHG 2010-08-10 huibong
// get_hashed_filepath 함수 정의 변경에 따른 코드 수정
char szHashResult[APR_MD5_DIGESTSIZE * 2 + 1];
if( get_hashed_filepath( pszResult, szHashResult, sizeof(szHashResult) ) == false )
{
// Clear array
memset( szHashResult, 0x00, sizeof(szHashResult));
// Write error log
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_auth_sp_new:get_hashed_filepath return false.[%s][%s][%zu]"
, pszResult, szHashResult, sizeof(szHashResult));
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG3("dav_auth_sp_new::pszResult=%s,hash=%s,pszCPW=%s", pszResult, szHashResult, pszCPW);
#endif
/* compare hashed password */
if (strcmp(szHashResult, pszCPW))
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_auth_sp_new: auth string failed: server %s client %s"
, szHashResult, pszCPW);
return !OK;
}
/* New Format */
r->user = apr_pstrcat(r->pool, r->user, "@", hashed_session_dump, NULL);
return OK;
}
/* Elenoa 2005.12.28 : SP-Authrization END */
static int dav_auth_check_basic_user(request_rec * r, char *pRcvdPasswd, int len, char *pszSafePasswd, struct account_cache *pac)
{
/* make user data */
r->user = apr_pstrcat(r->pool, pac->tran_id, "@", pac->seq, NULL);
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_check_basic_user::DB pass=%s", pac->pass);
#endif
/* DAV-Authrization */
if (strcmp(pszSafePasswd, pac->pass)) {
/* Elenoa 2005.12.28 : SP-Authrization START */
/* login failed */
char *pRcvdPasswdNew = apr_pcalloc(r->pool, len + 5);
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_check_basic_user:: padd IV:%s Key:%s", pac->iv, pac->pk);
#endif
/* copy a new set of inputed password string */
memcpy(pRcvdPasswdNew, pRcvdPasswd, len);
*(pRcvdPasswdNew + len) = '\0';
if (
#ifdef __USE_OLD_AUTH__
dav_auth_sp_old(r, pRcvdPasswdNew, len, pac) != OK
#else
(r->method_number == M_PUT &&
dav_auth_sp_old(r, pRcvdPasswdNew, len, pac) != OK) ||
r->method_number != M_PUT
#endif
) {
/* copy a new set of inputed password string */
memcpy(pRcvdPasswdNew, pRcvdPasswd, len);
*(pRcvdPasswdNew + len) = '\0';
if (dav_auth_sp_new(r, pRcvdPasswdNew, len, pac) != OK) {
//ap_note_basic_auth_failure(r);
return HTTP_UNAUTHORIZED;
}
/* Elenoa: 2007. 2. 1: not here */
#if 0
/* Elenoa: 2007. 1. 25: Add 'User Authorization' */
/* Here we check, if register SP's authorization server */
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER C (%d) %s", getpid(), pac->uri);
#endif
if (pac->uri[0] != '\0' && (retval = dav_auth_user(r, pac)) != OK) {
if (retval == HTTP_UNAUTHORIZED) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: user auth failed: (%s:%s)",
pac->seq, pac->tran_id);
return HTTP_PRECONDITION_FAILED;
}
}
#endif
}
/* Elenoa 2005.12.28 : SP-Authrization END */
}
return OK;
}
static int dav_auth_get_account_cache(request_rec *r, char *szVolumeID, struct account_cache *ac)
{
struct account_cache *pac;
memset((char *)ac, 0, sizeof(struct account_cache));
if ((pac = dav_shared_ac_get_by_vol(szVolumeID))) {
memcpy(ac, pac, sizeof(struct account_cache));
return 0;
}
// 201.07.15 dadamin
// 서비스 정보 없을 시 수행되던 cache 갱신 로직 삭제처리함
// 공유 메모리 쓰기 단일화(fimngd 수행) 위함
return -1;
}
#ifdef __CLOUD_STREAMING__
// 2012.12.18 dadamin
// Axissoft StarPlayer 인증 함수
bool check_starplayer_auth( request_rec * r )
{
// header Accept check
// 2013-08-05 : 해당 헤더 체크 기능 null 문자(값없음)까지 허용, "Accept:" 와 같은 형식
// 모마일(아이폰, 안드로이폰) 지원 시 해당 헤더 제거 할 수 없으므로
// 관련 헤더 null 문자(값없음)까지만 허용하기함
// 이는 Axissoft 측과 협의된 상태임
// 스타플레이어에서는 ACCEPT정보를 보내지 않으므로 서버변수 accept가 있으면
// 스타플레이어 외 다른 방식으로 접근한 케이스이므로 차단
char *acceptstr = NULL;
acceptstr = (char *)apr_table_get(r->headers_in, "Accept");
if(acceptstr && strlen(acceptstr) != 0)
{
//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
// "OPENDAV::check_starplayer_auth fail(Accept header field exist).[%s]",r->unparsed_uri);
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_starplayer_auth fail(Accept header field(%s)).[%s]"
, acceptstr, r->unparsed_uri);
return false;
}
// HTTP head 요청 경우 : Range, X-Streaming-Checksum 존재하지 않으므로 인증 통과
if(r->method_number == M_GET && r->header_only)
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_starplayer_auth HEAD request successed.[%s]",r->unparsed_uri);
return true;
}
// checksum
//a = range 문자열 예) "bytes=0-1023"
//b = checksum 예) 387
unsigned int checksum = 0;
const char* p = NULL;
p = apr_table_get(r->headers_in, "Range");
if(p == NULL)
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_starplayer_auth fail(Range not found).[%s]"
, r->unparsed_uri);
return false;
}
while (*p != 0)
{
checksum += *p++;
}
char buf[16];
int i = 0;
while (checksum && i < sizeof(buf))
{
char n = checksum & 0xf;
if (n < 10)
buf[i++] = n + '0';
else
buf[i++] = (n - 10) + 'a';
checksum >>= 4;
}
p = apr_table_get(r->headers_in, "X-Streaming-Checksum");
if(p == NULL)
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_starplayer_auth fail(X-Streaming-Checksum not found).[%s]"
, r->unparsed_uri);
return false;
}
while (i && p)
{
if (buf[--i] != *p++)
return false;
}
return (*p == 0 && i == 0);
}
int check_cloud_streaming_auth(request_rec * r)
{
const char * userAgent = NULL;
// 2012.12.18 dadamin
// Axissoft StarPlayer 인증을 처리 추가(양방향은 무인증 처리함)
userAgent = apr_table_get( r->headers_in, "User-Agent");
if(userAgent != NULL && strcmp(userAgent, "StarPlayer/1.0") == 0)
{
// Axissoft StarPlayer 인증
if( check_starplayer_auth(r) == false)
{
// Axissoft StarPlayer 인증 실패
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_starplayer_auth fail.[%s]",r->unparsed_uri);
return HTTP_UNAUTHORIZED;
}
else
{
// 무인증 처리를 위하여 서비스 name 설정
const char * xstreamdomain = NULL;
xstreamdomain = apr_table_get( r->headers_in, "X-Streaming-Domain");
if( xstreamdomain != NULL )
{
const char * p1 = NULL;
char * svc_name = NULL;
int svc_name_len = 0;
p1 = strchr( xstreamdomain, '.' );
if( p1 != NULL )
{
// 서비스 name 정보로 사용한다.
svc_name_len = (p1 - xstreamdomain);
svc_name = apr_pstrdup(r->pool, xstreamdomain);
*( svc_name + svc_name_len ) = '\0';
if(svc_name == NULL || strlen(svc_name) == 0)
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_cloud_streaming_auth: svc_name of X-Streaming-Domain is NULL.[%s][%s]",
xstreamdomain, r->unparsed_uri);
}
else
{
apr_table_setn(r->headers_in, "RedHost", svc_name );
// 2013.01.23 dadamin
// redirect된 경우에 대한 처리
// uri 규칙 : /dav/서비스명/파일path
// 이후 로직에서 정상 처리를 위해서 서비스명이 제거되어야함
ap_unescape_url( r->unparsed_uri );
if (strstr(r->unparsed_uri , "/dav/") == r->unparsed_uri)
{
if (strstr((r->unparsed_uri+5) , svc_name) == (r->unparsed_uri +5))
{
char * new_uri = NULL;
new_uri = r->unparsed_uri+ 5 + strlen(svc_name);
new_uri = apr_pstrcat(r->pool, "/dav", new_uri, NULL);
ap_parse_uri( r, new_uri );
ap_getparents( r->uri );
}
}
//is_anonymous = true;
return HTTP_NON_AUTHORITATIVE;
}
}
else
{
//is_anonymous = false;
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_cloud_streaming_auth: X-Streaming-Domain format is wrong [%s] [%s]",
xstreamdomain, r->unparsed_uri );
}
}
else
{
//is_anonymous = false;
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV::check_cloud_streaming_auth: X-Streaming-Domain not found [%s]",
r->unparsed_uri );
}
}
}
return HTTP_OK;
}
#endif // __CLOUD_STREAMING__
int dav_auth_authenticate(request_rec * r)
{
char *pszSafeUser = NULL;
char *pRcvdPasswd = NULL;
char *pszSafePasswd = NULL;
acct_info stAi;
int len, result;
struct account_cache ac;
apr_status_t rv;
//int is_user_auth = FALSE, is_band_ctrl = FALSE;
bool is_anonymous = false;
#ifdef __CLOUD_STREAMING__
int a = check_cloud_streaming_auth(r) ;
switch (a)
{
case HTTP_UNAUTHORIZED:
is_anonymous = false;
return HTTP_UNAUTHORIZED;
break;
case HTTP_NON_AUTHORITATIVE:
is_anonymous = true;
break;
default:
is_anonymous = false;
break;
}
#endif // __CLOUD_STREAMING__
// 2013.01.15 dadmain
// Axissoft StarPlayer 인증 실패 되어도 해당 요청이 무인증 디렉토리 경우
// 인증 처리 되어야 하기 때문에 기존 dav_shared_ar_get_value 함수 호출 될 수 있게 한다.
/* First, check anonymous */
if (is_anonymous == true || dav_shared_ar_get_value(r) == OK ) {
const char *domain;
char *p;
char szDomain[1024];
//int len;
#define ANONYMOUS_MD5 "246e939eeea2158750a7b68d10dbbf3f"
#define ANONYMOUS_AUTH_MD5 "ANONYMOUSCONNECTEDTHROUGHBROWSER"
#ifdef __OPENDAV_DEBUG_AUTH__
DBG0("dav_auth_authenticate: anonymous try to pass");
#endif
if (!(domain = apr_table_get(r->headers_in, "RedHost")))
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: anonymous RedHost Not Found. [%s]", r->unparsed_uri);
return DECLINED;
}
p = strchr(domain, '.');
len = (p ? p - domain : strlen(domain));
strncpy(szDomain, domain, len);
#if 0 // add by pizon
if (len > 1023) len = 1023
#endif
szDomain[len] = '\0';
// 2012-04-04 : dadamin
// dav_auth_get_account_cache < 0 경우 데이터베이스 에러이며, 에러는 503을 리턴 한다.
result = dav_auth_get_account_cache(r, szDomain, &ac);
if (result == 0 ) {
r->user = apr_pstrcat(r->pool, ac.tran_id, "@", ac.seq, "@", ANONYMOUS_AUTH_MD5, NULL);
if (dav_shared_ac_check_referer(&ac, r) != OK) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV: Referer Check Done, not permited");
return HTTP_BAD_REQUEST;
}
}
else if ( result < 0 )
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV::dav_auth_authenticate Error(ANONYMOUSCONNECTED) result[%s:%d]",szDomain, result);
return ( result == -2 ? HTTP_SERVICE_UNAVAILABLE : HTTP_BAD_REQUEST );
}
return OK;
}
if ((rv = dav_auth_get_pw_str(r, (const char **) &pRcvdPasswd)) != OK) {
#if 0
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_authenticate: dav_auth_get_pw_str: failed");
#endif
return rv;
}
/* From here, remained process start */
/* decode base64 encoding */
{
char *decoded, *temp;
decoded =
(char *) apr_palloc(r->pool, 8 +
(len = apr_base64_decode_len(pRcvdPasswd)));
memset(decoded, 0, len + 7);
len = apr_base64_decode(decoded, pRcvdPasswd);
*(decoded + len) = '\0';
temp = decoded;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_authenticate: decoded: %s", decoded);
#endif
r->user = ap_getword_nulls(r->pool, (const char **)&temp, ':');
r->ap_auth_type = "Basic";
#ifdef __OPENDAV_DEBUG_AUTH__
DBG2("dav_auth_authenticate: decoded split: %s, %s", r->user, temp);
#endif
pRcvdPasswd = temp; len = len - (strlen(r->user) + 1);
}
/* check validate id and password */
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_authenticate: CHECK POINT #1 %s", r->user);
#endif
pszSafeUser = apr_palloc(r->pool, 1 + strlen(r->user));
#ifdef __OPENDAV_DEBUG_AUTH__
DBG0("dav_auth_authenticate: CHECK POINT #2");
#endif
pszSafePasswd = apr_palloc(r->pool, 1 + strlen(pRcvdPasswd));
#ifdef __OPENDAV_DEBUG_AUTH__
DBG0("dav_auth_authenticate: CHECK POINT #3");
DBG1("dav_auth_authenticate::r->user = %s", r->user);
DBG2("dav_auth_authenticate::pRcvdPasswd = %s (%d)", pRcvdPasswd, len);
#ifdef __OPENDAV_DEBUG__
binary_dump(pRcvdPasswd, len);
#endif
#endif
check_string(pszSafeUser, r->user, strlen(r->user));
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_authenticate::pszSafeUser = %s", pszSafeUser);
#endif
check_string(pszSafePasswd, pRcvdPasswd, strlen(pRcvdPasswd));
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_authenticate::pszSafepasswd = %s", pszSafePasswd);
#endif
rv = at_split(pszSafeUser, &stAi);
//DBG1("dav_auth_authenticate::1st at_split = %d", res);
if (rv == -1) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_authenticate: at_split fail (%s)", r->user);
return HTTP_INTERNAL_SERVER_ERROR;
} else if (rv == -2) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_authenticate: user id format not match (%s)", r->user);
ap_note_basic_auth_failure(r);
return HTTP_UNAUTHORIZED;
}
#ifdef __OPENDAV_DEBUG_AUTH__
DBG1("dav_auth_authenticate::stAi.szVolumeID = %s", stAi.szVolumeID);
DBG1("dav_auth_authenticate::stAi.szUserID = %s", stAi.szUserID);
#endif
// 2012-04-04 : dadamin
// dav_auth_get_account_cache < 0 경우 데이터베이스 에러이며, 에러는 503을 리턴 한다.
/* check cached data */
result = dav_auth_get_account_cache(r, stAi.szVolumeID, &ac);
if (result < 0 )
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "OPENDAV::dav_auth_authenticate Error(Cache Check) result[%d]", result);
return (result == -2 ? HTTP_SERVICE_UNAVAILABLE : HTTP_BAD_REQUEST);
}
if ( strlen(ac.tran_id) == 0 )
{
ap_note_basic_auth_failure(r);
return HTTP_UNAUTHORIZED;
}
rv = dav_auth_check_basic_user(r, pRcvdPasswd, len, pszSafePasswd, &ac);
if (rv != OK) {
ap_note_basic_auth_failure(r);
return rv;
}
/* write to cache */
//dav_shared_ac_add(&ac);
return OK;
}
int dav_auth_authorization(request_rec * r)
{
char *user = r->user;
int m = r->method_number;
//apr_array_header_t *reqs_arr = (apr_array_header_t *) ap_requires(r);
apr_array_header_t *reqs_arr =
#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
NULL;
#else // 2.2.x
ap_requires(r);
#endif // 2.3 over
require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
register int x;
const char *t;
char *w;
#ifdef __OPENDAV_DEBUG_AUTH__
DBG0("dav_auth_authorization: enter");
#endif
// 2012.04.23 dadamin : 중복 처리 로직 삭제 처리
// /dav 인증 시 dav_auth_authenticat -> dav_auth_authorization 호출되며,
// dav_shared_ar_get_value함수 경우 dav_auth_authenticat 호출하여 처리함
//if (dav_shared_ar_get_value(r) == OK)
// return OK;
if (!reqs_arr) {
return DECLINED;
}
for (x = 0; x < reqs_arr->nelts; x++) {
if (!(reqs[x].method_mask & (1 << m)))
continue;
t = reqs[x].requirement;
w = ap_getword(r->pool, &t, ' ');
if (!strcmp(w, "valid-user")) {
return OK;
}
if (!strcmp(w, "user")) {
while (t[0]) {
w = ap_getword_conf(r->pool, &t);
if (!strcmp(user, w)) {
return OK;
}
}
}
}
return DECLINED;
}
/* Elenoa: 2007. 2. 2: dav_auth_user serial */
#define RECEIVE_CHUNK 1024
#define RECEIVE_RESERVED 5
static char *dav_auth_user_socket_recv(apr_pool_t *pool, apr_socket_t *sock, char *pszReceive)
{
char *pszTemp;
char szReceive[RECEIVE_CHUNK + RECEIVE_RESERVED];
apr_size_t bytes_read = RECEIVE_CHUNK;
apr_status_t rv;
char ebuf[128];
rv = apr_socket_recv(sock, szReceive, &bytes_read);
if (rv != APR_SUCCESS) {
apr_socket_close(sock);
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user_socket_recv: failure to recv message: %s",
apr_strerror(rv, ebuf, sizeof ebuf));
return NULL;
}
szReceive[bytes_read] = '\0';
if (pszReceive == NULL) {
pszTemp = apr_pstrdup(pool, szReceive);
} else {
pszTemp = apr_pstrcat(pool, pszReceive, szReceive, NULL);
}
return pszTemp;
}
#define CONTENT_LENGTH "Content-Length"
#define TRANSFER_CHUNKED "Transfer-Encoding: chunked"
static int dav_auth_user_body_type(char *pszReceive)
{
char *p, *r;
p = pszReceive;
while( (r = strstr(p, "\r\n")) )
{
// CHG 2012-04-21 huibong
// 포인터 위치 이동 관련 업무 flow 와 맞지 않아.. 수정 처리함.
//r += 2; p++;
r += 2;
p = r;
if( !strncasecmp(r, CONTENT_LENGTH, strlen(CONTENT_LENGTH)))
{
return 0;
}
if( !strncasecmp(r, TRANSFER_CHUNKED, strlen(TRANSFER_CHUNKED)))
{
return 1;
}
}
return -1;
}
#define VALIDATED_STRING "1000"
#define VALIDATED_FIELD "code"
#define PERMIT_FIELD "permitted_size"
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
#define CLASSIFIER "classified"
#endif
static int dav_auth_user_validate(request_rec *r, char *pszReceive, int is_chunked, apr_off_t *permitted)
{
char *p, *p2, *p3, *p4;
int retval = -1;
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
int classified = -1;
#endif // __CLASSIFIED_TRAFFIC_MANAGE__
p = pszReceive;
if ((p2 = strstr(p, "\r\n\r\n"))) {
p2 += 4;
if (is_chunked) {
/* we must skip one line more */
p = p2;
p2 = strstr(p, "\r\n");
if (!p2) return -1;
p2 += 2;
}
while (1) {
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER V (%d) %s", getpid(), p2);
#endif
if (!strncasecmp(p2, VALIDATED_FIELD, strlen(VALIDATED_FIELD)) &&
*(p2 + strlen(VALIDATED_FIELD)) == '|') {
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER V2 (%d) %s", getpid(), (p2 + strlen(VALIDATED_FIELD) + 1));
#endif
retval = 0;
if (!strncasecmp((p2 + strlen(VALIDATED_FIELD) + 1),
VALIDATED_STRING, strlen(VALIDATED_STRING))) {
retval = 1;
}
}
if (!strncasecmp(p2, PERMIT_FIELD, strlen(PERMIT_FIELD)) &&
*(p2 + strlen(PERMIT_FIELD)) == '|') {
if (permitted) {
*permitted = atoll((p2 + strlen(PERMIT_FIELD) + 1));
}
}
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
if (!strncasecmp(p2, CLASSIFIER, strlen(CLASSIFIER)) &&
*(p2 + strlen(CLASSIFIER)) == '|') {
if (classified == -1) {
classified = atoi((p2 + strlen(CLASSIFIER) + 1));
}
}
#endif
p3 = strstr(p2, "\r\n");
p4 = strchr(p2, '\n');
if (p3 == NULL && p4 == NULL)
break;
if (p3 != NULL && (p4 == NULL || (p3 < p4)))
p2 = p3 + 2;
if (p4 != NULL && (p3 == NULL || (p4 < p3)))
p2 = p4 + 1;
}
}
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
if (classified > -1) {
acct_info ai;
int rv = at_split(r->user, &ai);
if (rv == 1) {
sprintf(ai.szTCClassID, "%d", classified);
r->user = apr_pstrcat(r->pool, ai.szVolumeID, ".",
ai.szTCClassID, "@", ai.szUserID, "@",
ai.szSessionID, NULL);
}
}
#endif
return retval;
}
static int dav_auth_parse_byterange(char *range, apr_off_t clength,
apr_off_t *start, apr_off_t *end)
{
char *dash = strchr(range, '-');
char *errp;
apr_off_t number;
if (!dash) {
return 0;
}
if ((dash == range)) {
/* In the form "-5" */
if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
return 0;
}
*start = clength - number;
*end = clength - 1;
}
else {
*dash++ = '\0';
if (apr_strtoff(&number, range, &errp, 10) || *errp) {
return 0;
}
*start = number;
if (*dash) {
if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
return 0;
}
*end = number;
}
else { /* "5-" */
*end = clength - 1;
}
}
if (*start < 0) {
*start = 0;
}
if (*end >= clength) {
*end = clength - 1;
}
if (*start > *end) {
return -1;
}
return (*start > 0 || *end < clength);
}
static int dav_auth_parse_range(char *range, apr_off_t total, apr_off_t *req_be_sent, apr_off_t *start)
{
apr_off_t end = 0;
int retval;
*req_be_sent = 0;
*start = 0;
if (!range || strncasecmp(range, "bytes=", 6)) {
return 0;
}
range = range + 6;
retval = dav_auth_parse_byterange(range, total, start, &end);
*req_be_sent = (end - *start + 1);
return retval;
}
static void dav_auth_user_set_permitted(request_rec *r, apr_off_t start, apr_off_t permitted)
{
apr_table_unset(r->headers_in, "Range");
apr_table_setn(r->headers_in, "Range",
apr_psprintf(r->pool, "bytes=%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT,
start, (start + permitted - 1)));
}
/* Elenoa: 2007. 1. 25: Add 'User Authorization' */
int dav_auth_user_start(dav_resource_private *info)
{
apr_off_t req_be_sent, permitted, start;
char *range;
int retval;
if (!info->db_r || !info->db_r->r)
return !OK;
range = (char *)apr_table_get(info->db_r->r->headers_in, "Range");
range = apr_pstrdup(info->db_r->r->pool, range);
dav_auth_parse_range(range, info->finfo.size, &req_be_sent, &start);
if( req_be_sent == 0 )
req_be_sent = info->finfo.size;
retval = dav_auth_user(info->db_r->r, req_be_sent, &permitted);
if( retval != OK || permitted < 0 )
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "dav_auth_user_start: checked %s, permitted_size %" APR_OFF_T_FMT", FAILED!", retval == OK ? "OK" : "FAILED", permitted );
return (permitted < 0 ? HTTP_UNAUTHORIZED : retval);
}
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER PERMIT (%d) %" APR_OFF_T_FMT" /%" APR_OFF_T_FMT "", getpid(), permitted, req_be_sent);
#endif
if (permitted > 0 && req_be_sent > permitted)
{
dav_auth_user_set_permitted(info->db_r->r, start, permitted);
}
return OK;
}
//2012.03.07 : 상위 모듈에서 사용하고 있는 logio_config_t 값을 참조하기 위한 선언
module AP_MODULE_DECLARE_DATA logio_module;
typedef struct __dav_logio_config_t {
apr_off_t bytes_in;
apr_off_t bytes_out;
} dav_logio_config_t;
void dav_auth_user_end(dav_resource_private *info)
{
if( !info->db_r || !info->db_r->r )
return;
// mod_logio.so의 전송량 참조 : 주의 필요 - access_log 출력 후 관련 값은 초기화됨
dav_logio_config_t *cf = ap_get_module_config(info->db_r->r->connection->conn_config, &logio_module);
const char *cp = NULL;
cp = apr_table_get(info->db_r->r->headers_out, "Content-Length");
apr_int64_t clen = apr_atoi64(cp);
if (cf->bytes_out > 0)
{
// 2015.07.07 : dadamin
// 헤더가 포함된 값이므로 Content-Length 큰 경우 Content-Length 보냄
if (cf->bytes_out < clen)
dav_auth_user(info->db_r->r, cf->bytes_out, NULL);
else
dav_auth_user(info->db_r->r, clen, NULL);
}
else
dav_auth_user(info->db_r->r, info->db_r->r->bytes_sent, NULL);
return;
}
static const char c2x_table[] = "0123456789ABCDEF";
static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix, unsigned char *where)
{
#if APR_CHARSET_EBCDIC
what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
#endif /*APR_CHARSET_EBCDIC*/
*where++ = prefix;
*where++ = c2x_table[what >> 4];
*where++ = c2x_table[what & 0xf];
return where;
}
static char *dav_escape(apr_pool_t *p, const char *path)
{
char *copy = apr_palloc(p, 3 * strlen(path) + 3);
const unsigned char *s = (const unsigned char *)path;
unsigned char *d = (unsigned char *)copy;
unsigned c;
while( (c = *s) )
{
if( !isalpha(c) && !isdigit(c) )
{
d = c2x(c, '%', d);
}
else
{
(*d) = c;
d++;
}
++s;
}
*d = '\0';
return copy;
}
#ifdef __OPENDAV_USER_AUTH_GET
#define AUTH_USER_HEADER \
"GET %s?session_id=%s HTTP/1.1\r\n" \
"Host: %s:%d\r\n" \
"User-Agent: Opendav-%s\r\n" \
"\r\n"
#else
#define AUTH_USER_HEADER \
"POST %s HTTP/1.1\r\n" \
"Host: %s:%d\r\n" \
"Content-Type: application/x-www-form-urlencoded\r\n" \
"User-Agent: Opendav-%s\r\n" \
"Connection: Keep-Alive\r\n" \
"Content-Length: %d\r\n" \
"\r\n" \
"%s"
#endif
#define AUTH_USER_BODY_START \
"session_id=%s&" \
"uri=%s&" \
"ip=%s&" \
"req_size=%" APR_OFF_T_FMT ""
// 2017-11-03 CHG huibong (revision 1426, ir #31497)
// - 토토디스크 측에서 BILL 정보에 request_time, end_time 항목 추가를 요청하여 기능 추가
// - 현재는 일반 고객은 없지만 향후 발생될 수 있는 신규 고객에도 동일하게 제공
#define AUTH_USER_BODY_END \
"session_id=%s&" \
"uri=%s&" \
"ip=%s&" \
"sent_size=%" APR_OFF_T_FMT "" \
"&request_time=%" APR_TIME_T_FMT "" \
"&end_time=%" APR_TIME_T_FMT ""
#define AUTH_USER_BODY_REFERER \
"&referer=%s"
#define AUTH_USER_BODY_TIMESLICE \
"&time_%d=%" APR_UINT64_T_FMT ""
// 소프트 라인 업로드 파일 싱크 및 다운로드 과금 처리를 위한 필요한 KEY 값 정의
/// 2013-06-25 : SDK확장 정보(헤더에 SB_ExtSession) 추가로 고객사에서 구분할 수 있으므로 해당 값 정의 필요 없음
#ifdef __USE_AUTH_SOFTLINE_ONLY__
#define BILL_DOWNLOAD
#define BILL_UPLOAD
// 업로드 정보 전송관련 time out
#define BILL_UPLOAD_END_SEND_TIMEOUT 5 // sec
#define BILL_UPLOAD_END_RECV_TIMEOUT 1 // sec
#define BILL_UPLOAD_END \
"session_id=%s&" \
"uri=%s&" \
"ip=%s&" \
"file_size=%" APR_OFF_T_FMT ""
#endif // __USE_AUTH_SOFTLINE_ONLY__
/*
#define STRICTLY_AUTH_CODE "100"
#define IS_STRICTLY_AUTH(ac) \
(!strncmp(ac->mode, STRICTLY_AUTH_CODE, strlen(STRICTLY_AUTH_CODE)))
*/
#define IS_STRICTLY_AUTH(ac) (ac->mode[0] == '1')
#define IS_PERMIT_ANONYMOUS(ac) (ac->mode[1] == '0')
#define IS_PERMIT_DAV_AUTH(ac) (ac->mode[2] == '0')
#define IS_STRICTLY_ANONYMOUS(ac) (strlen(ac->mode) > 3 && ac->mode[3] == '1')
#define IS_PERMIT_EMPTY_REFERER(ac) (strlen(ac->mode) > 4 && ac->mode[4] == '1') /* using in "share.c" by pizon */
#define AU_PORT (permitted ? ac->auth_port : ac->bill_port)
#define AU_URI (permitted ? ac->auth_uri : ac->bill_uri)
#define AU_ADDR (permitted ? ac->auth_addr : ac->bill_addr)
#define AU_TIMEOUT (permitted ? ac->auth_timeout : ac->bill_timeout)
/*
** r [in] request 정보를 저장한 request_rec 객체에 대한 포인터
** content [in] 전송 요청 또는 실제 전송한 content size 정보
** permitted [out] 허용 여부 결과값을 저장할 포인터
** AUTH 요청인 경우 해당 객체는 NULL 아니지만, BILL 요청인 경우 NULL
*/
int dav_auth_user(request_rec *r, apr_off_t content, apr_off_t *permitted)
{
acct_info ai;
apr_status_t rv;
apr_socket_t *sock;
apr_sockaddr_t *sa;
char ebuf[128]; //, buf[120];
char *pszMessage
#ifndef __OPENDAV_USER_AUTH_GET
, *pszBody, *uri
#endif
;
apr_size_t bytes_send;
struct account_cache *ac;
const char *referer = apr_table_get(r->headers_in, "Referer");
char *pszReceive = NULL;
int is_chunked = 0, is_code;
// 2017-11-03 CHG huibong (revision 1426, ir #31497)
// - httpd version 별 request_rec 의 client ip 항목이 서로 달라 변수 처리.
const char *pszClientIP = NULL;
// 2018-01-25 huibong 토토지원 과금 IP 확인용 임시 코드
char tempBuffer[40];
memset( tempBuffer, 0x00, sizeof( tempBuffer ) );
if (permitted) *permitted = 0;
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER START (%d) %s", getpid(), r->user);
#endif
/* get session key from user string */
rv = at_split(r->user, &ai);
if (rv == -1) {
return HTTP_INTERNAL_SERVER_ERROR;
} else if (rv == -2) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_user: user id format not match (%s)", r->user);
return HTTP_UNAUTHORIZED;
}
/* get cache info */
ac = dav_shared_ac_get_by_tranid(ai.szVolumeID);
if (!ac) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_user: cache not found.. is possible? (%s)", r->user);
/* Internal Error Condition, i know.
* if process this routine, old-type-anonymous auth type.
* to prevent smiliar type of error, return OK */
return OK;
//return HTTP_INTERNAL_SERVER_ERROR;
}
if ((permitted ? !ac->auth_uri[0] : !ac->bill_uri[0])) {
return OK;
}
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER MODE %c%c%c",
ac->mode[0], ac->mode[1], ac->mode[2]);
#endif
/* if old-auth or dav-auth */
if (ai.szSessionID[0] == '\0') {
if (IS_PERMIT_DAV_AUTH(ac)) {
return OK;
} else {
return HTTP_UNAUTHORIZED;
}
}
if (!strcmp(ai.szSessionID, ANONYMOUS_AUTH_MD5)) {
if (!IS_STRICTLY_ANONYMOUS(ac))
return OK;
}
/* if anonymous */
/* soft-line auth 내부 test 시 주석처리 */
if (!strcmp(ai.szSessionID, ANONYMOUS_MD5)) {
if (IS_PERMIT_ANONYMOUS(ac)) {
return OK;
} else {
return HTTP_UNAUTHORIZED;
}
}
// fill socket address structure */
rv = apr_sockaddr_info_get(&sa, AU_ADDR, APR_INET, AU_PORT, 0, r->pool);
//rv = apr_sockaddr_info_get(&sa, "1.2.3.4", APR_INET, ac->port, 0, r->pool);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user: failure to open to '%s:%d': %s",
AU_ADDR, AU_PORT, apr_strerror(rv, ebuf, sizeof ebuf));
return HTTP_INTERNAL_SERVER_ERROR;
}
/* make socket */
rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, r->pool);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user: create socket: %s",
apr_strerror(rv, ebuf, sizeof ebuf));
return HTTP_INTERNAL_SERVER_ERROR;
}
/* set timeout */
rv = apr_socket_timeout_set(sock, apr_time_from_sec(AU_TIMEOUT));
if (rv != APR_SUCCESS) {
apr_socket_close(sock);
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user: set timeout: %s",
apr_strerror(rv, ebuf, sizeof ebuf));
return HTTP_INTERNAL_SERVER_ERROR;
}
/* connect */
rv = apr_socket_connect(sock, sa);
// 2018-01-25 huibong 토토지원 과금 IP 확인용 임시 코드
if( inet_ntop( AF_INET, &( sa->sa.sin.sin_addr ), tempBuffer, sizeof( tempBuffer ) ) == NULL )
{
sprintf( tempBuffer, "unknown" );
}
if (rv != APR_SUCCESS)
{
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user: connect socket error: (%s/%s/%s) %s(%s):%d/%s: %s",
ac->tran_id, ac->seq, ai.szSessionID, AU_ADDR, tempBuffer, AU_PORT,
AU_URI, apr_strerror( rv, ebuf, sizeof ebuf ) );
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
/*
else
{
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user: connect socket ok: (%s/%s/%s) %s(%s):%d/%s",
ac->tran_id, ac->seq, ai.szSessionID, AU_ADDR, tempBuffer, AU_PORT,
AU_URI );
}
*/
/* make message */
#ifdef __OPENDAV_USER_AUTH_GET
pszMessage = apr_psprintf(r->pool, AUTH_USER_HEADER,
AU_URI, ai.szSessionID, AU_ADDR, AU_PORT, VERSION);
#else
//uri = ap_os_escape_path(r->pool, r->uri, 1);
//uri = r->uri;
//uri = ap_escape_logitem(r->pool, r->uri);
uri = apr_pcalloc(r->pool, strlen(r->uri) + 3);
dav_repos_restore_unsafe_chars(r->uri, uri);
*(uri + strlen(r->uri)) = '\0';
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER URI %s (%d)", uri, getpid());
#endif
//uri = dav_escape(r->pool, r->uri);
uri = dav_escape(r->pool, uri);
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER ESCAPE URI %s (%d)", uri, getpid());
#endif
// 2017-11-03 CHG huibong (revision 1426, ir #31497)
// - Apache 버전별 client ip 정보 추출
#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
pszClientIP = r->connection->client_ip;
#else // 2.2.x
pszClientIP = r->connection->remote_ip;
#endif // 2.3 over
#ifdef __USE_AUTH_SOFTLINE_ONLY__
// 2017-11-03 CHG huibong (revision 1426, ir #31497)
// - 토토디스크 측에서 BILL 정보에 request_time, end_time 항목 추가를 요청하여 기능 추가
// - 기존에는 AUTH, BILL 인자 항목이 동일하여 문제 없었지만, BILL 항목에 2개가 추가되어 코드 분리 처리함.
// pszBody = apr_psprintf( r->pool,
// ( permitted ?
// ( referer ? AUTH_USER_BODY_START AUTH_USER_BODY_REFERER : AUTH_USER_BODY_START )
// : ( referer ? BILL_DOWNLOAD AUTH_USER_BODY_END AUTH_USER_BODY_REFERER : BILL_DOWNLOAD AUTH_USER_BODY_END ) ),
// ai.szSessionID,
//#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
// uri, r->connection->client_ip, content, referer );
//#else // 2.2.x
// uri, r->connection->remote_ip, content, referer);
//#endif // 2.3 over
if( permitted ) // AUTH 관련 처리인 경우
{
pszBody = apr_psprintf( r->pool, ( referer ? AUTH_USER_BODY_START AUTH_USER_BODY_REFERER : AUTH_USER_BODY_START )
, ai.szSessionID
, uri, pszClientIP, content
, referer );
}
else // BILL 관련 처리인 경우
{
pszBody = apr_psprintf( r->pool, ( referer ? BILL_DOWNLOAD AUTH_USER_BODY_END AUTH_USER_BODY_REFERER : BILL_DOWNLOAD AUTH_USER_BODY_END )
, ai.szSessionID
, uri, pszClientIP, content, r->request_time, apr_time_now()
, referer );
}
#else // !__USE_AUTH_SOFTLINE_ONLY__
// pszBody = apr_psprintf(r->pool,
// (permitted ?
// (referer ? AUTH_USER_BODY_START AUTH_USER_BODY_REFERER :
// AUTH_USER_BODY_START)
// :
// (referer ? AUTH_USER_BODY_END AUTH_USER_BODY_REFERER :
// AUTH_USER_BODY_END)),
// ai.szSessionID,
//#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
// uri, r->connection->client_ip, content, referer);
//#else // 2.2.x
// uri, r->connection->remote_ip, content, referer);
//#endif // 2.3 over
if( permitted ) // AUTH 관련 처리인 경우
{
pszBody = apr_psprintf( r->pool, ( referer ? AUTH_USER_BODY_START AUTH_USER_BODY_REFERER : AUTH_USER_BODY_START )
, ai.szSessionID
, uri, pszClientIP, content
, referer );
}
else // BILL 관련 처리인 경우
{
pszBody = apr_psprintf( r->pool, ( referer ? AUTH_USER_BODY_END AUTH_USER_BODY_REFERER : AUTH_USER_BODY_END )
, ai.szSessionID
, uri, pszClientIP, content, r->request_time, apr_time_now()
, referer );
}
#endif // !__USE_AUTH_SOFTLINE_ONLY__
// 2015.07.16 dadamin
// 해당 인터페이스 공통(SDK)으로 적용되었으므로 모듈에서 동일하게 적용함
if (!permitted)
{
// 2013-03-26 : dadamin
// 고객사(토토로사) 요청으로 웹하드 등록제 통과를 위해서 다운로드 완료 시
// 추가된 header data를 추가로 전송될 수 있게 한다.
const char *ExtSessionID;
if ((ExtSessionID = apr_table_get(r->headers_in, "SB_ExtSession")))
{
pszBody = apr_psprintf(r->pool,"%s&%s", pszBody, ExtSessionID);
}
else
{
// 해당 header가 없을 경우 단순 log 처리
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Extend the session does not exist.[%s]", uri);
}
}
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER MKBODY (%d)", getpid());
#endif
#ifdef __USE_AUTH_SOFTLINE_ONLY__
char szagent[20];
int ncontentlen = (int) strlen(pszBody);
// 소프트 라인에서 사용하고 있는 auth 경우 hearder가 고정크기이다.
// auth 경우 : 14+181, 과금 경우 : 14 + 184
// 고려 사항 : content length 경우 두자리, 네자리 숫자 염두
memset(szagent, 0, sizeof(szagent));
if( 9 < ncontentlen && ncontentlen < 100 ) // 두자리
{
strcpy(szagent, "WITH SOFTLINE ***");
}
else if ( 999 < ncontentlen ) // 네자리
{
strcpy(szagent, "WITH SOFTLINE *");
}
else // 나머지 (한자리,다섯자리 이상은 무시)
{
strcpy(szagent, "WITH SOFTLINE **");
}
pszMessage = apr_psprintf(r->pool, AUTH_USER_HEADER,
AU_URI, AU_ADDR, AU_PORT,
szagent, (int)strlen(pszBody), pszBody);
#else // __USE_AUTH_SOFTLINE_ONLY__
pszMessage = apr_psprintf(r->pool, AUTH_USER_HEADER,
AU_URI, AU_ADDR, AU_PORT,
VERSION, (int)strlen(pszBody), pszBody);
#endif // __SOFT_LINE_AUTH
#endif
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER E (%d) %s", getpid(), pszMessage);
#endif
/* send message */
bytes_send = strlen(pszMessage);
rv = apr_socket_send(sock, pszMessage, &bytes_send);
if (rv != APR_SUCCESS) {
apr_socket_close(sock);
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_user: failure to send message: (%s/%s/%s) %s:%d/%s: %s",
ac->tran_id, ac->seq, ai.szSessionID, AU_ADDR, AU_PORT,
AU_URI, apr_strerror(rv, ebuf, sizeof ebuf));
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
// 2011-03-20 소프트라인의 경우 인증은 응답대기, 과금은 응답대기하지 않도록 함.
#ifdef __USE_AUTH_SOFTLINE_ONLY__
if(permitted == NULL )
{
apr_socket_close(sock);
return OK;
}
#endif
/* receive message */
/* step 0: get header */
pszReceive = dav_auth_user_socket_recv(r->pool, sock, pszReceive);
if (pszReceive == NULL) {
apr_socket_close(sock);
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
/* step 1: parse content-length (or chunked) */
while ((is_chunked = dav_auth_user_body_type(pszReceive)) < 0) {
pszReceive = dav_auth_user_socket_recv(r->pool, sock, pszReceive);
if (pszReceive == NULL) {
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER ERR (%d) %s", getpid(), pszReceive);
#endif
apr_socket_close(sock);
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
}
/* step 2: get body */
/* step 3: check authrization */
while ((is_code = dav_auth_user_validate(r, pszReceive, is_chunked, permitted)) < 0) {
pszReceive = dav_auth_user_socket_recv(r->pool, sock, pszReceive);
if (pszReceive == NULL) {
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER ERR (%d) %s", getpid(), pszReceive);
#endif
apr_socket_close(sock);
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
}
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER D (%d) %s", getpid(), pszReceive);
#endif
apr_socket_close(sock);
return (is_code == 1 ? OK : HTTP_UNAUTHORIZED);
}
#ifdef __USE_AUTH_SOFTLINE_ONLY__
int dav_auth_upload_end_softline(request_rec *r, apr_off_t content, apr_off_t *permitted)
{
acct_info ai;
apr_status_t rv;
apr_socket_t *sock;
apr_sockaddr_t *sa;
char ebuf[128]; //, buf[120];
char *pszMessage
#ifndef __OPENDAV_USER_AUTH_GET
, *pszBody, *uri
#endif
;
apr_size_t bytes_send;
struct account_cache *ac;
const char *referer = apr_table_get(r->headers_in, "Referer");
if (permitted) *permitted = 0;
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER START (%d) %s", getpid(), r->user);
#endif
// 2016.05.27
// 위즈릴 제휴 컨텐츠 경우 FTP(SolDrive 마운트)를 통해서 업로드됨
// 이 경우 해당 과금 서버로 다수 요청될 수 있으므로 해당 과금 서버 안정성을 위해서 예외 처리함.
// 참고 : 해당 컨텐츠 업로드 완료 후 연동되는 인터페이스(ASP 구성된 서버)에서 과금서버(트랜스코딩요청)호출됨
const char * userAgent = NULL;
userAgent = apr_table_get( r->headers_in, "User-Agent");
if(userAgent != NULL && strncmp(userAgent, "NetCache", 8) == 0 )
{
if(r && r->server)
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "SKIP : Soldrive upload.[%s]", r->uri);
return OK;
}
/* get session key from user string */
rv = at_split(r->user, &ai);
if (rv == -1) {
return HTTP_INTERNAL_SERVER_ERROR;
} else if (rv == -2) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_upload_end_softline: user id format not match (%s)", r->user);
return HTTP_UNAUTHORIZED;
}
/* get cache info */
ac = dav_shared_ac_get_by_tranid(ai.szVolumeID);
if (!ac) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"dav_auth_upload_end_softline: cache not found.. is possible? (%s)", r->user);
/* Internal Error Condition, i know.
* if process this routine, old-type-anonymous auth type.
* to prevent smiliar type of error, return OK */
return OK;
//return HTTP_INTERNAL_SERVER_ERROR;
}
if ((permitted ? !ac->auth_uri[0] : !ac->bill_uri[0])) {
return OK;
}
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER MODE %c%c%c",
ac->mode[0], ac->mode[1], ac->mode[2]);
#endif
/* if old-auth or dav-auth */
if (ai.szSessionID[0] == '\0') {
// PUT not used;
}
if (!strcmp(ai.szSessionID, ANONYMOUS_AUTH_MD5)) {
if (!IS_STRICTLY_ANONYMOUS(ac))
return OK;
}
/* if anonymous */
/* soft-line auth 내부 test 시 주석처리 */
if (!strcmp(ai.szSessionID, ANONYMOUS_MD5)) {
if (IS_PERMIT_ANONYMOUS(ac)) {
return OK;
} else {
return HTTP_UNAUTHORIZED;
}
}
// fill socket address structure */
rv = apr_sockaddr_info_get(&sa, AU_ADDR, APR_INET, AU_PORT, 0, r->pool);
//rv = apr_sockaddr_info_get(&sa, "1.2.3.4", APR_INET, ac->port, 0, r->pool);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_upload_end_softline: failure to open to '%s:%d': %s",
AU_ADDR, AU_PORT, apr_strerror(rv, ebuf, sizeof ebuf));
return HTTP_INTERNAL_SERVER_ERROR;
}
/* make socket */
rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, r->pool);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_upload_end_softline: create socket: %s",
apr_strerror(rv, ebuf, sizeof ebuf));
return HTTP_INTERNAL_SERVER_ERROR;
}
/* set timeout */
rv = apr_socket_timeout_set(sock, apr_time_from_sec(BILL_UPLOAD_END_SEND_TIMEOUT));
if (rv != APR_SUCCESS) {
apr_socket_close(sock);
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_upload_end_softline: set timeout: %s",
apr_strerror(rv, ebuf, sizeof ebuf));
return HTTP_INTERNAL_SERVER_ERROR;
}
/* connect */
rv = apr_socket_connect(sock, sa);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_upload_end_softline: failure to connect socket: (%s/%s/%s - %" APR_OFF_T_FMT ") %s:%d/%s: %s",
ac->tran_id, ac->seq, r->uri, content, AU_ADDR, AU_PORT,
AU_URI, apr_strerror(rv, ebuf, sizeof ebuf));
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
/* make message */
#ifdef __OPENDAV_USER_AUTH_GET
pszMessage = apr_psprintf(r->pool, AUTH_USER_HEADER,
AU_URI, ai.szSessionID, AU_ADDR, AU_PORT, VERSION);
#else
//uri = ap_os_escape_path(r->pool, r->uri, 1);
//uri = r->uri;
//uri = ap_escape_logitem(r->pool, r->uri);
uri = apr_pcalloc(r->pool, strlen(r->uri) + 3);
dav_repos_restore_unsafe_chars(r->uri, uri);
*(uri + strlen(r->uri)) = '\0';
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER URI %s (%d)", uri, getpid());
#endif
//uri = dav_escape(r->pool, uri); 차진호 과장님 요청으로 URI인코딩하지 않음. 2011년 03월 21일
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER ESCAPE URI %s (%d)", uri, getpid());
#endif
#define FIXED_SESSION_ID "201S103wolt1920220h893ds10da3da3"
pszBody = apr_psprintf(r->pool,
(permitted ?
(referer ? AUTH_USER_BODY_START AUTH_USER_BODY_REFERER :
AUTH_USER_BODY_START)
:
(referer ? BILL_UPLOAD BILL_UPLOAD_END AUTH_USER_BODY_REFERER :
BILL_UPLOAD BILL_UPLOAD_END)),
FIXED_SESSION_ID,
#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
uri, r->connection->client_ip, content, referer);
#else // 2.2.x
uri, r->connection->remote_ip, content, referer);
#endif // 2.3 over
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER MKBODY (%d)", getpid());
#endif
if(!permitted)
{
// 2013-06-26 : dadamin
// 고객사(토토로사) 요청으로 솔루션 연동을 위해서 업로드 완료 후
// 추가된 header data를 추가로 전송될 수 있게 한다.
const char *ExtSessionID;
if ((ExtSessionID = apr_table_get(r->headers_in, "SB_ExtSession")))
{
pszBody = apr_psprintf(r->pool,"%s&%s", pszBody, ExtSessionID);
}
else
{
// 해당 header가 없을 경우 단순 log 처리
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "PUT Extend the session does not exist.[%s]", uri);
}
}
char szagent[20];
int ncontentlen = (int) strlen(pszBody);
// 소프트 라인에서 사용하고 있는 auth 경우 hearder가 고정크기이다.
// auth 경우 : 14+181, 과금 경우 : 14 + 184
// 고려 사항 : content length 경우 두자리, 네자리 숫자 염두
memset(szagent, 0, sizeof(szagent));
if( 9 < ncontentlen && ncontentlen < 100 ) // 두자리
{
strcpy(szagent, "WITH SOFTLINE ***");
}
else if ( 999 < ncontentlen ) // 네자리
{
strcpy(szagent, "WITH SOFTLINE *");
}
else // 나머지 (한자리,다섯자리 이상은 무시)
{
strcpy(szagent, "WITH SOFTLINE **");
}
pszMessage = apr_psprintf(r->pool, AUTH_USER_HEADER,
AU_URI, AU_ADDR, AU_PORT,
szagent, (int)strlen(pszBody), pszBody);
#endif
#ifdef __OPENDAV_DEBUG_USER_AUTH__
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "P_USER E (%d) %s", getpid(), pszMessage);
#endif
/* send message */
bytes_send = strlen(pszMessage);
rv = apr_socket_send(sock, pszMessage, &bytes_send);
if (rv != APR_SUCCESS) {
apr_socket_close(sock);
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"OPENDAV: dav_auth_upload_end_softline: failure to send message: (%s/%s/%s - %" APR_OFF_T_FMT ") %s:%d/%s: %s",
ac->tran_id, ac->seq, uri, content, AU_ADDR, AU_PORT,
AU_URI, apr_strerror(rv, ebuf, sizeof ebuf));
return IS_STRICTLY_AUTH(ac) ? HTTP_UNAUTHORIZED : HTTP_INTERNAL_SERVER_ERROR;
}
// 2011-03-20 huibong
// Upload 정보를 보내고 소프트라인 서버에 대한 응답대기를 하지 않는다. ( 차진호 과장 확인사항 )
apr_socket_close(sock);
return OK;
}
void dav_auth_upload_end(dav_resource_private *info)
{
#ifdef __USE_AUTH_SOFTLINE_ONLY_UPLOAD_END_SEND_
if (!info->db_r || !info->db_r->r)
return;
dav_auth_upload_end_softline(info->db_r->r, info->db_r->m_get_content_length, NULL);
#endif // __USE_AUTH_SOFTLINE_ONLY_UPLOAD_END_SEND_
return;
}
#endif // __USE_AUTH_SOFTLINE_ONLY__