造冰箱的大熊貓@cnblogs 2019/1/21
1、環境
操作系統/Ubuntu 16.04.5 LTS,內核/4.15.0-43-generic,convert/ImageMagick 6.8.9-9
2、問題
使用convert命令將一個jpeg格式的圖片文件轉換為pdf文檔時,提示“convert: not authorized `1.pdf` @ error/constitute.c/WriteImage/1028”錯誤。
$ convert 1.jpg 1.pdf convert: not authorized `1.pdf` @ error/constitute.c/WriteImage/1028. $
3、分析
不關心問題原因的,可以跳過這部分直接跳到下面的“4、排除故障”。
從sourceforge下載ImageMagick的源代碼壓縮包(版本6.8.9-10,沒找到6.8.9-9的源代碼)[1]。解壓縮獲得源代碼。
根據錯誤信息,在源代碼“magick”目錄下打開“constitute.c”文件,並跳轉到該文件的1028行(下面代碼中第6行)。從代碼中可以看到,錯誤是由於IsRightsAuthorized()函數返回錯誤導致的。
domain=CoderPolicyDomain;
rights=WritePolicyRights;
if (IsRightsAuthorized(domain,rights,write_info->magick) == MagickFalse)
{
sans_exception=DestroyExceptionInfo(sans_exception);
write_info=DestroyImageInfo(write_info);
errno=EPERM;
ThrowBinaryException(PolicyError,"NotAuthorized",filename);
}
打開“policy.c” 文件,找到IsRightsAuthorized()函數的代碼(如下所示),判斷函數返回失敗(MagickFalse)是由於給定的PolicyDomian和PoicyRights與policy_cache中的值不匹配導致的。
MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
const PolicyRights rights,const char *pattern)
{
const PolicyInfo
*policy_info;
ExceptionInfo
*exception;
MagickBooleanType
authorized;
register PolicyInfo
*p;
(void) LogMagickEvent(PolicyEvent,GetMagickModule(),
"Domain: %s; rights=%s; pattern=\"%s\" ...",
CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
exception=AcquireExceptionInfo();
policy_info=GetPolicyInfo("*",exception);
exception=DestroyExceptionInfo(exception);
if (policy_info == (PolicyInfo *) NULL)
return(MagickTrue);
authorized=MagickTrue;
LockSemaphoreInfo(policy_semaphore);
ResetLinkedListIterator(policy_cache);
p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
{
if ((p->domain == domain) &&
(GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
{
if (((rights & ReadPolicyRights) != 0) &&
((p->rights & ReadPolicyRights) == 0))
authorized=MagickFalse;
if (((rights & WritePolicyRights) != 0) &&
((p->rights & WritePolicyRights) == 0))
authorized=MagickFalse;
if (((rights & ExecutePolicyRights) != 0) &&
((p->rights & ExecutePolicyRights) == 0))
authorized=MagickFalse;
}
p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
}
UnlockSemaphoreInfo(policy_semaphore);
return(authorized);
}
在該文件中繼續搜索,發現policy_cache由IsPolicyCacheInstantiated()函數從PolicyFilename指向的文件中讀取。而PolicyFilename為“policy.xml”(#define PolicyFilename "policy.xml")。
static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
{
if (policy_cache == (LinkedListInfo *) NULL)
{
if (policy_semaphore == (SemaphoreInfo *) NULL)
ActivateSemaphoreInfo(&policy_semaphore);
LockSemaphoreInfo(policy_semaphore);
if (policy_cache == (LinkedListInfo *) NULL)
policy_cache=AcquirePolicyCache(PolicyFilename,exception);
UnlockSemaphoreInfo(policy_semaphore);
}
return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
}
在“/etc/ImageMagick-6”下搜索到“policy.xml”文件。根據該文件中給出的注釋信息,pdf文件的權限被設置為“none”,要想獲得寫權限,需增加“write”權限。具體操作步驟參考“4、排除故障”。
在policy.xml禁止pdf寫權限是在Ubuntu的某次安全性升級時實施的[2],具體與imagemagickluanchpad的安全策略相關[ 3]。沒仔細研究到底是什么情況,有興趣的研究明白的請告知。
4、排除故障
使用文件編輯器打開“/etc/ImageMagick-6/policy.xml”,找到類似“<policy domain="coder" rights="none" pattern="PDF" />”的一行,將其中的“none”改為“write”,保存文件。重新執行convert命令即可。
參考
