1 /*****************************************************************************
2 *  Copyright 2005 Alt-N Technologies, Ltd.
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  This code incorporates intellectual property owned by Yahoo! and licensed
11 *  pursuant to the Yahoo! DomainKeys Patent License Agreement.
12 *
13 *  Unless required by applicable law or agreed to in writing, software
14 *  distributed under the License is distributed on an "AS IS" BASIS,
15 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *  See the License for the specific language governing permissions and
17 *  limitations under the License.
18 *
19 *****************************************************************************/
20 
21 #ifdef WIN32
22 #include <windows.h>
23 #pragma warning( disable: 4786 )
24 #else
25 #endif
26 
27 #include "dkim.h"
28 #include "dkimsign.h"
29 #include "dkimverify.h"
30 #include "resource.h"
31 #include <string.h>
32 
33 #define DKIMID ('D' | 'K'<<8 | 'I'<<16 | 'M'<<24)
34 
35 #ifdef WIN32
36 //////////////////////////////////////////////////////////////////////
37 // DllMain
38 //////////////////////////////////////////////////////////////////////
DllMain(HANDLE hModule,DWORD dwReason,LPVOID lpReserved)39 BOOL APIENTRY DllMain( HANDLE hModule,
40                        DWORD  dwReason,
41                        LPVOID lpReserved
42 					 )
43 {
44 
45 	switch (dwReason)
46 	{
47 		case DLL_PROCESS_ATTACH:
48 			//g_Instance = (HINSTANCE)hModule;
49 			break;
50 
51 		case DLL_PROCESS_DETACH:
52 			break;
53 	}
54 
55     return TRUE;
56 }
57 #endif // #ifdef WIN32
58 
59 
InitContext(DKIMContext * pContext,bool bSign,void * pObject)60 static void InitContext( DKIMContext* pContext, bool bSign, void* pObject )
61 {
62 	pContext->reserved1 = DKIMID;
63 	pContext->reserved2 = bSign ? 1 : 0;
64 	pContext->reserved3 = pObject;
65 }
66 
ValidateContext(DKIMContext * pContext,bool bSign)67 static void* ValidateContext( DKIMContext* pContext, bool bSign )
68 {
69 	if( pContext->reserved1 != DKIMID )
70 		return NULL;
71 
72 	if( pContext->reserved2 != (unsigned int)(bSign ? 1 : 0) )
73 		return NULL;
74 
75 	return pContext->reserved3;
76 }
77 
DKIMSignInit(DKIMContext * pSignContext,DKIMSignOptions * pOptions)78 int DKIM_CALL DKIMSignInit( DKIMContext* pSignContext, DKIMSignOptions* pOptions )
79 {
80 	int nRet = DKIM_OUT_OF_MEMORY;
81 
82 	CDKIMSign* pSign = new CDKIMSign;
83 
84 	if( pSign )
85 	{
86 		nRet = pSign->Init( pOptions );
87 
88 		if( nRet != DKIM_SUCCESS )
89 			delete pSign;
90 	}
91 
92 	if( nRet == DKIM_SUCCESS )
93 	{
94 		InitContext( pSignContext, true, pSign );
95 	}
96 
97 	return nRet;
98 }
99 
100 
DKIMSignProcess(DKIMContext * pSignContext,char * szBuffer,int nBufLength)101 int DKIM_CALL DKIMSignProcess( DKIMContext* pSignContext, char* szBuffer, int nBufLength )
102 {
103 	CDKIMSign* pSign = (CDKIMSign*)ValidateContext( pSignContext, true );
104 
105 	if( pSign )
106 	{
107 		return pSign->Process( szBuffer, nBufLength, false );
108 	}
109 
110 	return DKIM_INVALID_CONTEXT;
111 }
112 
113 
DKIMSignGetSig(DKIMContext * pSignContext,char * szPrivKey,char * szSignature,int nSigLength)114 int DKIM_CALL DKIMSignGetSig( DKIMContext* pSignContext, char* szPrivKey, char* szSignature, int nSigLength )
115 {
116 	CDKIMSign* pSign = (CDKIMSign*)ValidateContext( pSignContext, true );
117 
118 	if( pSign )
119 	{
120 		return pSign->GetSig( szPrivKey, szSignature, nSigLength );
121 	}
122 
123 	return DKIM_INVALID_CONTEXT;
124 }
125 
DKIMSignGetSig2(DKIMContext * pSignContext,char * szPrivKey,char ** pszSignature)126 int DKIM_CALL DKIMSignGetSig2( DKIMContext* pSignContext, char* szPrivKey, char** pszSignature )
127 {
128 	CDKIMSign* pSign = (CDKIMSign*)ValidateContext( pSignContext, true );
129 
130 	if( pSign )
131 	{
132 		return pSign->GetSig2( szPrivKey, pszSignature );
133 	}
134 
135 	return DKIM_INVALID_CONTEXT;
136 
137 }
138 
139 
140 
DKIMSignFree(DKIMContext * pSignContext)141 void DKIM_CALL DKIMSignFree( DKIMContext* pSignContext )
142 {
143 	CDKIMSign* pSign = (CDKIMSign*)ValidateContext( pSignContext, true );
144 
145 	if( pSign )
146 	{
147 		delete pSign;
148 		pSignContext->reserved3 = NULL;
149 	}
150 }
151 
152 
DKIMVerifyInit(DKIMContext * pVerifyContext,DKIMVerifyOptions * pOptions)153 int DKIM_CALL DKIMVerifyInit( DKIMContext* pVerifyContext, DKIMVerifyOptions* pOptions )
154 {
155 	int nRet = DKIM_OUT_OF_MEMORY;
156 
157 	CDKIMVerify* pVerify = new CDKIMVerify;
158 
159 	if( pVerify )
160 	{
161 		nRet = pVerify->Init( pOptions );
162 		if( nRet != DKIM_SUCCESS )
163 			delete pVerify;
164 	}
165 
166 	if( nRet == DKIM_SUCCESS )
167 	{
168 		InitContext( pVerifyContext, false, pVerify );
169 	}
170 
171 	return nRet;
172 }
173 
174 
DKIMVerifyProcess(DKIMContext * pVerifyContext,char * szBuffer,int nBufLength)175 int DKIM_CALL DKIMVerifyProcess( DKIMContext* pVerifyContext, char* szBuffer, int nBufLength )
176 {
177 	CDKIMVerify* pVerify = (CDKIMVerify*)ValidateContext( pVerifyContext, false );
178 
179 	if( pVerify )
180 	{
181 		return pVerify->Process( szBuffer, nBufLength, false );
182 	}
183 
184 	return DKIM_INVALID_CONTEXT;
185 }
186 
187 
DKIMVerifyResults(DKIMContext * pVerifyContext)188 int DKIM_CALL DKIMVerifyResults( DKIMContext* pVerifyContext )
189 {
190 	CDKIMVerify* pVerify = (CDKIMVerify*)ValidateContext( pVerifyContext, false );
191 
192 	if( pVerify )
193 	{
194 		return pVerify->GetResults();
195 	}
196 
197 	return DKIM_INVALID_CONTEXT;
198 }
199 
200 
DKIMVerifyGetDetails(DKIMContext * pVerifyContext,int * nSigCount,DKIMVerifyDetails ** pDetails,char * szPractices)201 int DKIM_CALL DKIMVerifyGetDetails( DKIMContext* pVerifyContext, int* nSigCount, DKIMVerifyDetails** pDetails, char* szPractices )
202 {
203 	szPractices[0] = '\0';
204 
205 	CDKIMVerify* pVerify = (CDKIMVerify*)ValidateContext( pVerifyContext, false );
206 
207 	if( pVerify )
208 	{
209 		strcpy(szPractices, pVerify->GetPractices());
210 		return pVerify->GetDetails(nSigCount, pDetails);
211 	}
212 
213 	return DKIM_INVALID_CONTEXT;
214 }
215 
216 
DKIMVerifyFree(DKIMContext * pVerifyContext)217 void DKIM_CALL DKIMVerifyFree( DKIMContext* pVerifyContext )
218 {
219 	CDKIMVerify* pVerify = (CDKIMVerify*)ValidateContext( pVerifyContext, false );
220 
221 	if( pVerify )
222 	{
223 		delete pVerify;
224 		pVerifyContext->reserved3 = NULL;
225 	}
226 }
227 
228 
DKIMVersion()229 char* DKIM_CALL DKIMVersion()
230 {
231 	return VERSION_STRING;
232 }
233 
234 
235 static char* DKIMErrorStrings[-1-DKIM_MAX_ERROR] = {
236 	"DKIM_FAIL",
237 	"DKIM_BAD_SYNTAX",
238 	"DKIM_SIGNATURE_BAD",
239 	"DKIM_SIGNATURE_BAD_BUT_TESTING",
240 	"DKIM_SIGNATURE_EXPIRED",
241 	"DKIM_SELECTOR_INVALID",
242 	"DKIM_SELECTOR_GRANULARITY_MISMATCH",
243 	"DKIM_SELECTOR_KEY_REVOKED",
244 	"DKIM_SELECTOR_DOMAIN_NAME_TOO_LONG",
245 	"DKIM_SELECTOR_DNS_TEMP_FAILURE",
246 	"DKIM_SELECTOR_DNS_PERM_FAILURE",
247 	"DKIM_SELECTOR_PUBLIC_KEY_INVALID",
248 	"DKIM_NO_SIGNATURES",
249 	"DKIM_NO_VALID_SIGNATURES",
250 	"DKIM_BODY_HASH_MISMATCH",
251 	"DKIM_SELECTOR_ALGORITHM_MISMATCH",
252 	"DKIM_STAT_INCOMPAT",
253 	"DKIM_UNSIGNED_FROM",
254 	"DKIM_OUT_OF_MEMORY",
255 	"DKIM_INVALID_CONTEXT",
256 	"DKIM_NO_SENDER",
257 	"DKIM_BAD_PRIVATE_KEY",
258 	"DKIM_BUFFER_TOO_SMALL",
259 };
260 
261 
DKIMGetErrorString(int ErrorCode)262 char* DKIM_CALL DKIMGetErrorString( int ErrorCode )
263 {
264 	if (ErrorCode >= 0 || ErrorCode <= DKIM_MAX_ERROR)
265 		return "Unknown";
266 	else
267 		return DKIMErrorStrings[-1-ErrorCode];
268 }
269