summaryrefslogtreecommitdiff
path: root/libdigidoc/DigiDocService.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdigidoc/DigiDocService.c')
-rw-r--r--libdigidoc/DigiDocService.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/libdigidoc/DigiDocService.c b/libdigidoc/DigiDocService.c
new file mode 100644
index 0000000..ce471a3
--- /dev/null
+++ b/libdigidoc/DigiDocService.c
@@ -0,0 +1,341 @@
+//==================================================
+// FILE: DigiDocService.c
+// PROJECT: Digi Doc
+// DESCRIPTION: Digi Doc functions for DigiDocService access
+// AUTHOR: Veiko Sinivee, Sunset Software O†
+//==================================================
+// Copyright (C) AS Sertifitseerimiskeskus
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+// GNU Lesser General Public Licence is available at
+// http://www.gnu.org/copyleft/lesser.html
+//==================================================
+
+// config data comes from there
+#include <config.h>
+#include <libdigidoc/DigiDocConfig.h>
+#include <libdigidoc/DigiDocService.h>
+#include <libdigidoc/DigiDocDebug.h>
+#include <libdigidoc/DigiDocMem.h>
+#include <libdigidoc/DigiDocObj.h>
+#include <libdigidoc/DigiDocConvert.h>
+#include <libdigidoc/DigiDocGen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+char* g_xmlHdr1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:d=\"http://www.sk.ee/DigiDocService/DigiDocService_2_3.wsdl\"><SOAP-ENV:Body SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><d:MobileCreateSignature>";
+char* g_xmlEnd1 = "</d:MobileCreateSignature></SOAP-ENV:Body></SOAP-ENV:Envelope>";
+char* g_xmlHdr2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:d=\"http://www.sk.ee/DigiDocService/DigiDocService_2_3.wsdl\"><SOAP-ENV:Body SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><d:GetMobileCreateSignatureStatus>";
+char* g_xmlEnd2 = "</d:GetMobileCreateSignatureStatus></SOAP-ENV:Body></SOAP-ENV:Envelope>";
+
+char* g_ddsUrl = "https://digidocservice.sk.ee/DigiDocService";
+
+int ddocXmlElem(DigiDocMemBuf* pMbuf, const char* szElem, const char* szValue)
+{
+ int err = ERR_OK;
+ if(szValue) {
+ err = ddocGen_startElem(pMbuf, szElem);
+ if(!err)
+ err = ddocMemAppendData(pMbuf, szValue, -1);
+ if(!err)
+ err = ddocGen_endElem(pMbuf, szElem);
+ }
+ return err;
+}
+
+int findXmlElemValue(DigiDocMemBuf* pMbMsg, const char* szTag, DigiDocMemBuf* pMbValue)
+{
+ char *p1, *p2;
+ char tag[50];
+
+ p1 = (char*)pMbMsg->pMem;
+ if(p1) {
+ snprintf(tag, sizeof(tag), "<%s", szTag);
+ p1 = strstr(p1, tag);
+ if(p1) {
+ while(*p1 && *p1 != '>') p1++;
+ if(*p1 && *p1 == '>') p1++;
+ snprintf(tag, sizeof(tag), "</%s", szTag);
+ p2 = strstr(p1, tag);
+ if(p2 && p1 && (long)p2 > (long)p1) {
+ ddocMemAssignData(pMbValue, p1, (int)(p2 - p1));
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
+
+
+//--------------------------------------------------
+// Signs the document and gets return status back
+// pSigDoc - signed document object
+// szIdCode - personal id code
+// szPhoneNo - users phone number
+// szLang - language code
+// manifest - manifest or role
+// city - signers address , city
+// state - signers address , state or province
+// zip - signers address , postal code
+// country - signers address , country name
+// pSesscode - pointer to long int buffer for returning session code
+// szChallenge - buffer for returning challenge code (char 4)
+// nChalLen - length of challenge buffer
+// return error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddsSign(SignedDoc* pSigDoc,
+ const char* szIdCode, const char* szPhoneNo,
+ const char* szLang, const char* szServiceName,
+ const char* manifest, const char* city,
+ const char* state, const char* zip,
+ const char* country,
+ char* url, char* proxyHost, char* proxyPort,
+ long* pSesscode, char* szChallenge, int nChalLen)
+{
+ int err = ERR_OK, i, l1;
+ char *p1 = 0;
+ DataFile *pDf = 0;
+ DigiDocMemBuf mbuf1, mbuf2, mbuf3;
+ char buf1[40];
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ mbuf2.pMem = 0;
+ mbuf2.nLen = 0;
+ mbuf3.pMem = 0;
+ mbuf3.nLen = 0;
+ ddocDebug(3, "ddsSign", "Creating M-ID signature using: %s", szPhoneNo);
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ RETURN_IF_NULL_PARAM(szIdCode);
+ RETURN_IF_NULL_PARAM(country);
+ RETURN_IF_NULL_PARAM(szPhoneNo);
+ //RETURN_IF_NULL_PARAM(url);
+ if(url == NULL)
+ url = g_ddsUrl;
+ RETURN_IF_NULL_PARAM(pSesscode);
+ RETURN_IF_NULL_PARAM(szChallenge);
+ ddocMemAssignData(&mbuf2, g_xmlHdr1, -1);
+ // create xml request
+ err = ddocXmlElem(&mbuf2, "IDCode", szIdCode);
+ err = ddocXmlElem(&mbuf2, "SignersCountry", country);
+ err = ddocXmlElem(&mbuf2, "PhoneNo", szPhoneNo);
+ err = ddocXmlElem(&mbuf2, "Language", szLang);
+ err = ddocXmlElem(&mbuf2, "ServiceName", szServiceName);
+ err = ddocXmlElem(&mbuf2, "Role", manifest);
+ err = ddocXmlElem(&mbuf2, "City", city);
+ err = ddocXmlElem(&mbuf2, "StateOrProvince", state);
+ err = ddocXmlElem(&mbuf2, "PostalCode", zip);
+ err = ddocXmlElem(&mbuf2, "CountryName", country);
+ err = ddocGen_startElem(&mbuf2, "DataFiles");
+ for(i = 0; i < getCountOfDataFiles(pSigDoc); i++) {
+ pDf = getDataFile(pSigDoc, i);
+ err = ddocGen_startElem(&mbuf2, "DataFileDigest");
+ err = ddocXmlElem(&mbuf2, "Id", pDf->szId);
+ err = ddocXmlElem(&mbuf2, "DigestType", pDf->szDigestType);
+ l1 = sizeof(buf1);
+ memset(buf1, 0, l1);
+ encode((const byte*)pDf->mbufDigest.pMem, pDf->mbufDigest.nLen, (byte*)buf1, &l1);
+ err = ddocXmlElem(&mbuf2, "DigestValue", buf1);
+ err = ddocGen_endElem(&mbuf2, "DataFileDigest");
+ }
+ err = ddocGen_endElem(&mbuf2, "DataFiles");
+ err = ddocXmlElem(&mbuf2, "Format", pSigDoc->szFormat);
+ err = ddocXmlElem(&mbuf2, "Version", pSigDoc->szFormatVer);
+ sprintf(buf1, "S%d", getNextSignatureId(pSigDoc));
+ err = ddocXmlElem(&mbuf2, "SignatureID", buf1);
+ err = ddocXmlElem(&mbuf2, "MessagingMode", "asynchClientServer");
+ err = ddocXmlElem(&mbuf2, "AsyncConfiguration", "0");
+ ddocMemAppendData(&mbuf2, g_xmlEnd1, -1);
+
+ // create http req
+ ddocMemAssignData(&mbuf1, "POST ", -1);
+ if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) {
+ ddocMemAppendData(&mbuf1, url, -1);
+ } else {
+ p1 = strstr(url, "://");
+ if(p1) p1 += 3;
+ if(p1) p1 = strchr(p1, '/');
+ if(p1)
+ ddocMemAppendData(&mbuf1, p1, -1);
+ else
+ ddocMemAppendData(&mbuf1, "/", -1);
+ }
+ ddocMemAppendData(&mbuf1, " HTTP/1.0\r\n", -1);
+ ddocMemAppendData(&mbuf1, "User-Agent: DigiDocLib\r\n", -1);
+ ddocMemAppendData(&mbuf1, "Content-Type: text/xml; charset=utf-8\r\n", -1);
+ snprintf(buf1, sizeof(buf1), "Content-Length: %d\r\n", (int)mbuf2.nLen);
+ ddocMemAppendData(&mbuf1, buf1, -1);
+ ddocMemAppendData(&mbuf1, "Connection: Close\r\n", -1);
+ if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) // if we use proxy then send also Proxy-Connection
+ ddocMemAppendData(&mbuf1, "Proxy-Connection: Close\r\n", -1);
+ ddocMemAppendData(&mbuf1, "SOAPAction: \"\"\r\n", -1);
+ ddocMemAppendData(&mbuf1, "\r\n", -1);
+ ddocMemAppendData(&mbuf1, mbuf2.pMem, mbuf2.nLen);
+ ddocDebug(4, "ddsSign", "Send to host: %s request len: %d", url, mbuf1.nLen);
+ ddocDebug(4, "ddsSign", "Sending: \n---\n%s\n---\n", mbuf1.pMem);
+ ddocMemBuf_free(&mbuf2);
+ err = ddocPullUrl(url, &mbuf1, &mbuf2, proxyHost, proxyPort);
+ ddocDebug(4, "ddsSign", "Recevied len: %d RC: %d", mbuf2.nLen, err);
+ //ddocDebug(3, "ddsSign", "Received: \n---\n%s\n---\n", mbuf2.pMem);
+ if(!err && ((l1 = ddocGetHttpResponseCode(&mbuf2)) == 200)) {
+ err = ddocGetHttpPayload(&mbuf2, &mbuf3);
+ ddocMemBuf_free(&mbuf2);
+ ddocDebug(4, "ddsSign", "SOAP: \n---\n%s\n---\n", mbuf3.pMem);
+ err = findXmlElemValue(&mbuf3, "Sesscode", &mbuf2);
+ if(!err)
+ (*pSesscode) = atol((char*)mbuf2.pMem);
+ //ddocDebug(3, "ddsSign", "Sesscode: %ld", (*pSesscode));
+ ddocMemBuf_free(&mbuf2);
+ err = findXmlElemValue(&mbuf3, "ChallengeID", &mbuf2);
+ //ddocDebug(3, "ddsSign", "Challenge id %s", mbuf2.pMem);
+ if(!err && mbuf2.pMem && mbuf2.nLen) {
+ memset(szChallenge, 0, nChalLen);
+ strncpy(szChallenge, mbuf2.pMem, mbuf2.nLen);
+ }
+ ddocDebug(3, "ddsSign", "Sesscode: %ld Challenge id %s RC: %d", (*pSesscode), szChallenge, err);
+ ddocMemBuf_free(&mbuf2);
+ }
+
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ ddocMemBuf_free(&mbuf3);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ return err;
+}
+
+//------------------------------------------
+// Gets DigiDocService session status and returns status code
+// If session is ready then signature will be returned
+// pSigDoc - signed document object to be modified
+// lSesscode - session code
+// url - dds service url
+// proxyHost - proxy hostname
+// proxyPort -proxy port
+// pStatus - buffer for returning status
+// pMBufSig - buffer for returning signature
+// returns DigiDocService session status code
+// deprecated use ddsGetStatus(pSigDoc, lSesscode, url, proxyHost, proxyPort, pStatus, szFileName)
+//------------------------------------------
+DIGIDOC_DEPRECATED EXP_OPTION int ddsGetStatus(SignedDoc* pSigDoc, long lSesscode,
+ char* url, char* proxyHost, char* proxyPort,
+ int* pStatus)
+{
+ return ddsGetStatusWithFile(pSigDoc, lSesscode, url, proxyHost, proxyPort, pStatus, NULL);
+}
+
+//------------------------------------------
+// Gets DigiDocService session status and returns status code
+// If session is ready then signature will be returned
+// pSigDoc - signed document object to be modified
+// lSesscode - session code
+// url - dds service url
+// proxyHost - proxy hostname
+// proxyPort -proxy port
+// pStatus - buffer for returning status
+// szFileName - ddoc filename to add signature from dds (optional)
+// pMBufSig - buffer for returning signature
+// returns DigiDocService session status code
+//------------------------------------------
+EXP_OPTION int ddsGetStatusWithFile(SignedDoc* pSigDoc, long lSesscode,
+ char* url, char* proxyHost, char* proxyPort,
+ int* pStatus, const char* szFileName)
+{
+ int err = ERR_OK, l1;
+ SignatureInfo *pSigInfo = 0;
+ DigiDocMemBuf mbuf1, mbuf2, mbuf3;
+ char buf1[40], *p1;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ mbuf2.pMem = 0;
+ mbuf2.nLen = 0;
+ mbuf3.pMem = 0;
+ mbuf3.nLen = 0;
+ ddocDebug(3, "ddsGetStatus", "Get Status for sess: %ld", lSesscode);
+ RETURN_IF_NULL_PARAM(pSigDoc);
+ //RETURN_IF_NULL_PARAM(url);
+ if(url == NULL)
+ url = g_ddsUrl;
+ RETURN_IF_NULL_PARAM(pStatus);
+ *pStatus = 0;
+ ddocMemAssignData(&mbuf2, g_xmlHdr2, -1);
+ // create xml request
+ sprintf(buf1, "%ld", lSesscode);
+ err = ddocXmlElem(&mbuf2, "Sesscode", buf1);
+ err = ddocXmlElem(&mbuf2, "WaitSignature", "false");
+ ddocMemAppendData(&mbuf2, g_xmlEnd2, -1);
+
+ // create http req
+ ddocMemAssignData(&mbuf1, "POST ", -1);
+ if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) {
+ ddocMemAppendData(&mbuf1, url, -1);
+ } else {
+ p1 = strstr(url, "://");
+ if(p1) p1 += 3;
+ if(p1) p1 = strchr(p1, '/');
+ if(p1)
+ ddocMemAppendData(&mbuf1, p1, -1);
+ else
+ ddocMemAppendData(&mbuf1, "/", -1);
+ }
+ ddocMemAppendData(&mbuf1, " HTTP/1.0\r\n", -1);
+ ddocMemAppendData(&mbuf1, "User-Agent: DigiDocLib\r\n", -1);
+ ddocMemAppendData(&mbuf1, "Content-Type: text/xml; charset=utf-8\r\n", -1);
+ snprintf(buf1, sizeof(buf1), "Content-Length: %d\r\n", (int)mbuf2.nLen);
+ ddocMemAppendData(&mbuf1, buf1, -1);
+ ddocMemAppendData(&mbuf1, "Connection: Close\r\n", -1);
+ if(proxyHost || (proxyPort && atoi(proxyPort) > 0)) // if we use proxy then send also Proxy-Connection
+ ddocMemAppendData(&mbuf1, "Proxy-Connection: Close\r\n", -1);
+ ddocMemAppendData(&mbuf1, "SOAPAction: \"\"\r\n", -1);
+ ddocMemAppendData(&mbuf1, "\r\n", -1);
+ ddocMemAppendData(&mbuf1, mbuf2.pMem, mbuf2.nLen);
+ ddocDebug(4, "ddsGetStatus", "Send to host: %s request len: %d", url, mbuf1.nLen);
+ ddocDebug(4, "ddsGetStatus", "Sending: \n---\n%s\n---\n", mbuf1.pMem);
+ ddocMemBuf_free(&mbuf2);
+ err = ddocPullUrl(url, &mbuf1, &mbuf2, proxyHost, proxyPort);
+ ddocDebug(4, "ddsGetStatus", "Recevied len: %d RC: %d", mbuf2.nLen, err);
+ //ddocDebug(3, "ddsSign", "Received: \n---\n%s\n---\n", mbuf2.pMem);
+ if(!err && ((l1 = ddocGetHttpResponseCode(&mbuf2)) == 200)) {
+ err = ddocGetHttpPayload(&mbuf2, &mbuf3);
+ ddocMemBuf_free(&mbuf2);
+ ddocDebug(4, "ddsGetStatus", "SOAP: \n---\n%s\n---\n", mbuf3.pMem);
+ err = findXmlElemValue(&mbuf3, "Status", &mbuf2);
+ if(!err && mbuf2.pMem) {
+ if(!strcmp((char*)mbuf2.pMem, "OUTSTANDING_TRANSACTION"))
+ (*pStatus) = STATUS_OUTSTANDING_TRANSACTION;
+ if(!strcmp((char*)mbuf2.pMem, "SIGNATURE"))
+ (*pStatus) = STATUS_SIGNATURE;
+ if(!strcmp((char*)mbuf2.pMem, "ERROR"))
+ (*pStatus) = STATUS_ERROR;
+
+ }
+ ddocDebug(3, "ddsGetStatus", "Sesscode: %ld Status: %d RC: %d", lSesscode, (*pStatus), err);
+ ddocMemBuf_free(&mbuf2);
+ if((*pStatus) == STATUS_SIGNATURE) {
+ err = findXmlElemValue(&mbuf3, "Signature", &mbuf2);
+ ddocDebug(4, "ddsGetStatus", "Sig-esacped: \n---\n%s\n---\n", mbuf2.pMem);
+ p1 = escape2xmlsym((char*)mbuf2.pMem);
+ ddocDebug(4, "ddsGetStatus", "Signature: \n---\n%s\n---\n", p1);
+ err = ddocAddSignatureFromMemory(pSigDoc, szFileName, (const void*)p1, strlen(p1));
+ /*sprintf(buf1, "S%d", getNextSignatureId(pSigDoc));
+ SignatureInfo_new(&pSigInfo, pSigDoc, buf1);
+ ddocMemAssignData(&(pSigInfo->mbufOrigContent), p1, -1);*/
+ free(p1);
+ }
+ }
+
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ ddocMemBuf_free(&mbuf3);
+ RETURN_IF_NOT(err == ERR_OK, err);
+ return err;
+}
+